The ARM compiler toolchain supports an interface to the status
word in the floating-point environment. This interface is provided
as function __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.
The function prototype for __ieee_status() is:
unsigned int __ieee_status(unsigned int mask, unsigned int flags);
Note
This function requires you to select a floating-point model
that supports exceptions. For example, --fpmode=ieee_full or --fpmode=ieee_fixed.
__ieee_status() 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.
Table 4. 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 2.
The fields in Figure 2 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.
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. See Table 5.
Table 5. Rounding mode control
| Bits | Rounding mode |
|---|
00 | Round to nearest |
01 | Round up |
10 | Round down |
11 | Round toward zero |
Note
The fz*, fj* and f* library
variants 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. (The relevant compiler options
are --fpmode=std, --fpmode=ieee_no_fenv and --fpmode=ieee_fixed.)
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.
Note
The FZ bit in the IEEE status
word is not supported by any of the fplib variants. This
means that switching between flushing to zero and not flushing to
zero is not possible with any variant of fplib at runtime.
However, flushing to zero or not flushing to zero can be set at
compile time as a result of the library you choose to build with.
Some functions are not provided in hardware. They
exist only in the software floating-point libraries. So these functions
cannot support the FZ mode, even when you are compiling for a hardware
VFP architecture. As a result, behavior of the floating-point libraries
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 the following 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
call:
__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);
See also
- Tasks
Using ARM C and C++ Libraries and Floating-Point
Support:
- Concepts
Using
ARM C and C++ Libraries and Floating-Point Support:
- Reference