Function core::arch::x86_64::_mm_setcsr
1.27.0 · source · pub unsafe fn _mm_setcsr(val: u32)
_mm_setcsr
documentation - use inline assembly insteadsse
and x86-64 only.Expand description
Sets the MXCSR register with the 32-bit unsigned integer value.
This register controls how SIMD instructions handle floating point operations. Modifying this register only affects the current thread.
It contains several groups of flags:
-
Exception flags report which exceptions occurred since last they were reset.
-
Masking flags can be used to mask (ignore) certain exceptions. By default these flags are all set to 1, so all exceptions are masked. When an an exception is masked, the processor simply sets the exception flag and continues the operation. If the exception is unmasked, the flag is also set but additionally an exception handler is invoked.
-
Rounding mode flags control the rounding mode of floating point instructions.
-
The denormals-are-zero mode flag turns all numbers which would be denormalized (exponent bits are all zeros) into zeros.
Note that modifying the masking flags, rounding mode, or denormals-are-zero mode flags leads to immediate Undefined Behavior: Rust assumes that these are always in their default state and will optimize accordingly. This even applies when the register is altered and later reset to its original value without any floating-point operations appearing in the source code between those operations (since floating-point operations appearing earlier or later can be reordered).
If you need to perform some floating-point operations under a different masking flags, rounding mode, or denormals-are-zero mode, use an inline assembly block and make sure to restore the original MXCSR register state before the end of the block.
§Exception Flags
-
_MM_EXCEPT_INVALID
: An invalid operation was performed (e.g., dividing Infinity by Infinity). -
_MM_EXCEPT_DENORM
: An operation attempted to operate on a denormalized number. Mainly this can cause loss of precision. -
_MM_EXCEPT_DIV_ZERO
: Division by zero occurred. -
_MM_EXCEPT_OVERFLOW
: A numeric overflow exception occurred, i.e., a result was too large to be represented (e.g., anf32
with absolute value greater than2^128
). -
_MM_EXCEPT_UNDERFLOW
: A numeric underflow exception occurred, i.e., a result was too small to be represented in a normalized way (e.g., anf32
with absulte value smaller than2^-126
.) -
_MM_EXCEPT_INEXACT
: An inexact-result exception occurred (a.k.a. precision exception). This means some precision was lost due to rounding. For example, the fraction1/3
cannot be represented accurately in a 32 or 64 bit float and computing it would cause this exception to be raised. Precision exceptions are very common, so they are usually masked.
Exception flags can be read and set using the convenience functions
_MM_GET_EXCEPTION_STATE
and _MM_SET_EXCEPTION_STATE
. For example, to
check if an operation caused some overflow:
_MM_SET_EXCEPTION_STATE(0); // clear all exception flags
// perform calculations
if _MM_GET_EXCEPTION_STATE() & _MM_EXCEPT_OVERFLOW != 0 {
// handle overflow
}
§Masking Flags
There is one masking flag for each exception flag: _MM_MASK_INVALID
,
_MM_MASK_DENORM
, _MM_MASK_DIV_ZERO
, _MM_MASK_OVERFLOW
,
_MM_MASK_UNDERFLOW
, _MM_MASK_INEXACT
.
A single masking bit can be set via
However, since mask bits are by default all set to 1, it is more common to want to disable certain bits. For example, to unmask the underflow exception, use:
Warning: an unmasked exception will cause an exception handler to be
called.
The standard handler will simply terminate the process. So, in this case
any underflow exception would terminate the current process with something
like signal: 8, SIGFPE: erroneous arithmetic operation
.
§Rounding Mode
The rounding mode is describe using two bits. It can be read and set using
the convenience wrappers _MM_GET_ROUNDING_MODE()
and
_MM_SET_ROUNDING_MODE(mode)
.
The rounding modes are:
-
_MM_ROUND_NEAREST
: (default) Round to closest to the infinite precision value. If two values are equally close, round to even (i.e., least significant bit will be zero). -
_MM_ROUND_DOWN
: Round toward negative Infinity. -
_MM_ROUND_UP
: Round toward positive Infinity. -
_MM_ROUND_TOWARD_ZERO
: Round towards zero (truncate).
Example:
§Denormals-are-zero/Flush-to-zero Mode
If this bit is set, values that would be denormalized will be set to zero instead. This is turned off by default.
You can read and enable/disable this mode via the helper functions
_MM_GET_FLUSH_ZERO_MODE()
and _MM_SET_FLUSH_ZERO_MODE()
:
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_OFF); // turn off (default)
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); // turn on