Intel 64 and IA-32 Architectures Software Developers Manual Volume 1, Basic Architecture
Vol. 1 E-21
GUIDELINES FOR WRITING SIMD FLOATING-POINT EXCEPTION HANDLERS
E.4.3 Example SIMD Floating-Point Emulation Implementation
The sample code listed below may be considered as being part of a user-level
floating-point exception filter for the SSE/SSE2/SSE3 numeric instructions. It is
assumed that the filter function is invoked by a low-level exception handler (reached
via interrupt vector 19 when an unmasked floating-point exception occurs), and that
it operates as explained in Section E.4.1, “Floating-Point Emulation.” The sample
code does the emulation only for the SSE instructions for addition, subtraction, multi-
plication, and division. For this, it uses C code and x87 FPU operations. Operations
corresponding to other SSE/SSE2/SSE3 numeric instructions can be emulated simi-
larly. The example assumes that the emulation function receives a pointer to a data
structure specifying a number of input parameters: the operation that caused the
exception, a set of sub-operands (unpacked, of type float), the rounding mode (the
precision is always single), exception masks (having the same relative bit positions
as in the MXCSR but starting from bit 0 in an unsigned integer), and flush-to-zero
and denormals-are-zeros indicators.
The output parameters are a floating-point result (of type float), the cause of the
exception (identified by constants not explicitly defined below), and the exception
status flags. The corresponding C definition is:
typedef struct {
unsigned int operation; //SSE or SSE2 operation: ADDPS, ADDSS, ...
unsigned int operand1_uint32; //first operand value
unsigned int operand2_uint32; //second operand value (if any)
float result_fval; // result value (if any)
unsigned int rounding_mode; //rounding mode
unsigned int exc_masks; //exception masks, in the order P,U,O,Z,D,I
unsigned int exception_cause; //exception cause
unsigned int status_flag_inexact; //inexact status flag
unsigned int status_flag_underflow; //underflow status flag
unsigned int status_flag_overflow; //overflow status flag
unsigned int status_flag_divide_by_zero;
//divide by zero status flag
unsigned int status_flag_denormal_operand;
//denormal operand status flag
unsigned int status_flag_invalid_operation;
//invalid operation status flag
unsigned int ftz; // flush-to-zero flag
unsigned int daz; // denormals-are-zeros flag
} EXC_ENV;