|
|
Libraries and Floating Point Support Guide
Writing a custom exception trap handler
Writing a custom
exception trap handlerNoteThe following functionality requires you to select a floating-point
model that supports exceptions, such as --fpmode=ieee_full or --fpmode=ieee_fixed. If you want to install a custom exception trap handler, declare
it as a function like this:
__softfp__ieee_value_t myhandler(__ieee_value_t op1,
__ieee_value_t op2,
__ieee_edata_t edata);
The parameters to this function are: op1,
op2These are used to give the
operands, or the intermediate result, for the operation that caused
the exception: For the Invalid Operation
and Divide by Zero exceptions, the original operands are supplied. For the Inexact Result exception, all that is supplied
is the ordinary result that would have been returned anyway. This
is provided in op1. For the Overflow exception, an intermediate result
is provided. This result is calculated by working out what the operation
would have returned if the exponent range had been big enough, and
then adjusting the exponent so that it fits in the format. The exponent
is adjusted by 192 (0xC0) in single-precision,
and by 1536 (0x600) in double-precision. If Overflow happens when converting a double to
a float, the result is supplied in double format,
rounded to single-precision, with the exponent biased by 192. For the Underflow exception, a similar intermediate
result is produced, but the bias value is added to the exponent
instead of being subtracted. The edata parameter
also contains a flag to show whether the intermediate result has
had to be rounded up, down, or not at all.
The type __ieee_value_t is defined as a
union of all the possible types that an operand can be passed as:
typedef union{
float __f;
float __s;
double __d;
short __h;
unsigned short __uh;
int __i;
unsigned int __ui;
long long __l;
unsigned long long __ul;
...
/* __STRICT_ANSI__ */
struct { int __word1, __word2; } __str;
} __ieee_value_t; /* in and out values passed to traps */
NoteIf you do not compile with --strict, and
you have code that used the older definition of __ieee_value_t,
your older code still works. See the file fenv.h for more
information. edataThis
contains flags that give information about the exception that occurred,
and what operation was being performed. (The type __ieee_edata_t is
a synonym for unsigned int.) __softfp__ieee_value_t
myhandlerThe return value from
the function is used as the result of the operation that caused
the exception.
edata flags for exception trap handler
The flags contained in edata are: edata & FE_EX_RDIRThis is nonzero if the intermediate result in Underflow
was rounded down, and 0 if it was rounded up or not rounded. (The
difference between the last two is given in the Inexact Result bit.)
This bit is meaningless for any other type of exception. edata & FE_EX_exceptionThis is nonzero if the given exception (INVALID, DIVBYZERO, OVERFLOW, UNDERFLOW, or INEXACT)
occurred. This enables you to: use
the same handler function for more than one exception type (the function
can test these bits to tell what exception it is supposed to handle) determine whether Overflow and Underflow intermediate
results have been rounded or are exact.
Because the FE_EX_INEXACT bit can be set
in combination with either FE_EX_OVERFLOW or FE_EX_UNDERFLOW,
you must determine the type of exception that actually occurred
by testing Overflow and Underflow before testing Inexact. edata & FE_EX_FLUSHZEROThis is nonzero if the FZ bit
was set when the operation was performed. edata & FE_EX_ROUND_MASKThis gives the rounding mode that applies to the
operation. This is normally the same as the current rounding mode,
unless the operation that caused the exception was a routine such
as _ffix, that always rounds toward zero. The
available rounding mode values are FE_EX_ROUND_NEAREST, FE_EX_ROUND_PLUSINF, FE_EX_ROUND_MINUSINF and FE_EX_ROUND_ZERO. edata & FE_EX_INTYPE_MASKThis gives the type of the operands to the function,
as one of the type values shown in Table 20. Table 20. FE_EX_INTYPE_MASK operand type
flags | Flag | Operand type |
|---|
FE_EX_INTYPE_FLOAT | float | FE_EX_INTYPE_DOUBLE | double | FE_EX_INTYPE_FD | float double | FE_EX_INTYPE_DF | double float | FE_EX_INTYPE_HALF | short | FE_EX_INTYPE_INT | int | FE_EX_INTYPE_UINT | unsigned int | FE_EX_INTYPE_LONGLONG | long long | FE_EX_INTYPE_ULONGLONG | unsigned long long |
edata & FE_EX_OUTTYPE_MASKThis gives the type of the operands to the function,
as one of the type values shown in Table 21. Table 21. FE_EX_OUTTYPE_MASK operand type
flags | Flag | Operand type |
|---|
FE_EX_OUTTYPE_FLOAT | float | FE_EX_OUTTYPE_DOUBLE | double | FE_EX_OUTTYPE_HALF | short | FE_EX_OUTTYPE_INT | int | FE_EX_OUTTYPE_UINT | unsigned int | FE_EX_OUTTYPE_LONGLONG | long long | FE_EX_OUTTYPE_ULONGLONG | unsigned long long |
edata & FE_EX_FN_MASKThis gives the nature of the operation that caused
the exception, as one of the operation codes shown in Table 22. Table 22. FE_EX_FN_MASK operation type flags | Flag | Operation type |
|---|
FE_EX_FN_ADD | Addition. | FE_EX_FN_SUB | Subtraction. | FE_EX_FN_MUL | Multiplication. | FE_EX_FN_DIV | Division. | FE_EX_FN_REM | Remainder. | FE_EX_FN_RND | Round to integer. | FE_EX_FN_SQRT | Square root. | FE_EX_FN_CMP | Compare. | FE_EX_FN_CVT | Convert between formats. | FE_EX_FN_LOGB | Exponent fetching. | FE_EX_FN_SCALBN | Scaling. NoteThe FE_EX_INTYPE_MASK flag only specifies
the type of the first operand. The second operand is always an int. | FE_EX_FN_NEXTAFTER | Next representable number. NoteBoth operands are the same type. Calls to nexttoward cause the
value of the second operand to change to a value that is of the
same type as the first operand. This does not affect the result. | FE_EX_FN_RAISE | The exception was raised explicitly, by feraiseexcept() or feupdateenv().
In this case, almost nothing in the edata word
is valid. |
When the operation is a comparison, the result must be returned
as if it were an int, and must be one of the four values
shown in Table 23. Input and output types are the same for all operations except
Compare and Convert. Table 23. FE_EX_CMPRET_MASK comparison type
flags | Flag | Comparison |
|---|
FE_EX_CMPRET_LESS | op1 is less than op2 | FE_EX_CMPRET_EQUAL | op1 is equal to op2 | FE_EX_CMPRET_GREATER | op1 is greater than op2 | FE_EX_CMPRET_UNORDERED | op1 and op2 are not comparable |
See also
- Tasks
- Concepts
- Reference
ARM
C and C++ Libraries and Floating-Point Support Reference: Compiler Reference:
|