Intel 64 and IA-32 Architectures Software Developers Manual Volume 1, Basic Architecture
E-24 Vol. 1
GUIDELINES FOR WRITING SIMD FLOATING-POINT EXCEPTION HANDLERS
int uiopd1; // first operand of the add, subtract, multiply, or divide
int uiopd2; // second operand of the add, subtract, multiply, or divide
float res; // result of the add, subtract, multiply, or divide
double dbl_res24; // result with 24-bit significand, but "unbounded" exponent
// (needed to check tininess, to provide a scaled result to
// an underflow/overflow trap handler, and in flush-to-zero mode)
double dbl_res; // result in double precision format (needed to avoid a
// double rounding error when denormalizing)
unsigned int result_tiny;
unsigned int result_huge;
unsigned short int sw; // 16 bits
unsigned short int cw; // 16 bits
// have to check first for faults (V, D, Z), and then for traps (O, U, I)
// initialize x87 FPU (floating-point exceptions are masked)
_asm {
fninit;
}
result_tiny = 0;
result_huge = 0;
switch (exc_env->operation) {
case ADDPS:
case ADDSS:
case SUBPS:
case SUBSS:
case MULPS:
case MULSS:
case DIVPS:
case DIVSS:
uiopd1 = exc_env->operand1_uint32; // copy as unsigned int
// do not copy as float to avoid conversion
// of SNaN to QNaN by compiled code
uiopd2 = exc_env->operand2_uint32;
// do not copy as float to avoid conversion of SNaN
// to QNaN by compiled code
uiopd1 = check_for_daz (uiopd1); // operand1 = +0.0 * operand1 if it is
// denormal and DAZ=1
uiopd2 = check_for_daz (uiopd2); // operand2 = +0.0 * operand2 if it is
// denormal and DAZ=1
// execute the operation and check whether the invalid, denormal, or
// divide by zero flags are set and the respective exceptions enabled
// set control word with rounding mode set to exc_env->rounding_mode,
// single precision, and all exceptions disabled