| |||
| Home > Floating-point Support > Controlling the floating-point environment > __ieee_status() |
RVCT supports an interface to the status word in the floating-point
environment. This is called __ieee_status and
it is generally the most efficient function to use for modifying
the status word for VFP. __ieee_status is defined
in fenv.h.
__ieee_status has the prototype:
unsigned int __ieee_status(unsigned int mask, unsigned int flags);
The function modifies the writable parts of the status word according to the parameters, and returns the previous value of the whole word.
The writable bits are modified by setting them to:
new = (old & ~mask) ^ flags;
Four different operations can be performed on each bit of the status word, depending on the corresponding bits in mask and flags (see Table 4.6).
Table 4.6. Status word bit modification
| Bit of mask | Bit of flags | Effect |
|---|---|---|
| 0 | 0 | Leave alone |
| 0 | 1 | Toggle |
| 1 | 0 | Set to 0 |
| 1 | 1 | Set to 1 |
The layout of the status word as seen by __ieee_status is
shown in Figure 4.1.
The fields in Figure 4.1 are as follows:
Bits 0 to 4 (values 0x1 to 0x10,
respectively) are the sticky flags, or cumulative flags, for each
exception. The sticky flag for an exception is set to 1 whenever
that exception happens and is not trapped. Sticky flags are never
cleared by the system, only by the user. The mapping of exceptions
to bits is:
bit 0 (0x01)
is for the Invalid Operation exception
bit 1 (0x02) is for the Divide
by Zero exception
bit 2 (0x04) is for the Overflow
exception
bit 3 (0x08) is for the Underflow
exception
bit 4 (0x10) is for the Inexact
Result exception.
Bits 8 to 12 (values 0x100 to 0x1000)
are the exception masks. These control whether each exception is
trapped or not. If a bit is set to 1, the corresponding exception
is trapped. If a bit is set to 0, the corresponding exception sets
its sticky flag and returns a plausible result, as described in Exceptions.
Bits 16 to 18, and bits 20 and 21, are used by VFP
hardware to control the VFP vector capability. The __ieee_status call
does not let you modify these bits.
Bits 22 and 23 control the rounding mode (Table 4.7).
Table 4.7. Rounding mode control
| Bits | Rounding mode |
|---|---|
00 |
Round to nearest |
01 |
Round up |
10 |
Round down |
11 |
Round toward zero |
The standard fplib libraries f* support
only the Round to nearest rounding mode. If you require support
for the other rounding modes, you must use the full IEEE g* libraries.
See Library naming conventions.
Bit 24 enables FZ (Flush to Zero) mode if it is set. In FZ mode, denormals are forced to zero to speed up processing (because denormals can be difficult to work with and slow down floating-point systems). Setting this bit reduces accuracy but might increase speed.
The standard fplib libraries do not support the FZ mode. Instead, each library either always flushes to zero or never flushes to zero, and you choose the library to use at build time. Only the VFP hardware honors the FZ mode if bit 24 is set.
However, this means that functions that are not provided in the hardware (and so are supplied in software fplib) do not support the FZ mode even when compiling for hard VFP. As a result, the behavior of fplib is not consistent across all functions when you change the FZ mode dynamically.
Bit 27 indicates that saturation has occurred in
an advanced SIMD saturating integer operation. This is accessible
through the __ieee_status call.
Bits marked R are reserved. They cannot be written
to by the __ieee_status call, and you must
ignore anything you find in them.
In addition to defining the __ieee_status call
itself, fenv.h also defines some constants to
be used for the arguments:
#define FE_IEEE_FLUSHZERO (0x01000000) #define FE_IEEE_ROUND_TONEAREST (0x00000000) #define FE_IEEE_ROUND_UPWARD (0x00400000) #define FE_IEEE_ROUND_DOWNWARD (0x00800000) #define FE_IEEE_ROUND_TOWARDZERO (0x00C00000) #define FE_IEEE_ROUND_MASK (0x00C00000) #define FE_IEEE_MASK_INVALID (0x00000100) #define FE_IEEE_MASK_DIVBYZERO (0x00000200) #define FE_IEEE_MASK_OVERFLOW (0x00000400) #define FE_IEEE_MASK_UNDERFLOW (0x00000800) #define FE_IEEE_MASK_INEXACT (0x00001000) #define FE_IEEE_MASK_ALL_EXCEPT (0x00001F00) #define FE_IEEE_INVALID (0x00000001) #define FE_IEEE_DIVBYZERO (0x00000002) #define FE_IEEE_OVERFLOW (0x00000004) #define FE_IEEE_UNDERFLOW (0x00000008) #define FE_IEEE_INEXACT (0x00000010) #define FE_IEEE_ALL_EXCEPT (0x0000001F)
For example, to set the rounding mode to round down, you would do:
__ieee_status(FE_IEEE_ROUND_MASK, FE_IEEE_ROUND_DOWNWARD);
To trap the Invalid Operation exception and untrap all other exceptions:
__ieee_status(FE_IEEE_MASK_ALL_EXCEPT, FE_IEEE_MASK_INVALID);
To untrap the Inexact Result exception:
__ieee_status(FE_IEEE_MASK_INEXACT, 0);
To clear the Underflow sticky flag:
__ieee_status(FE_IEEE_UNDERFLOW, 0);