/* Copyright Greg Novak, released to the public domain */

#include "intel-fp-exceptions.h"

#define X87_INVALID_OPERATION      0x1 
#define X87_DENORMALIZED_OPERAND   0x2
#define X87_DIVIDE_BY_ZERO         0x4
#define X87_NUMERIC_OVERFLOW       0x8
#define X87_NUMERIC_UNDERFLOW     0x10
#define X87_INEXACT_RESULT        0x20

#define SSE_INVALID_OPERATION     0x80
#define SSE_DENORMALIZED_OPERAND 0x100
#define SSE_DIVIDE_BY_ZERO       0x200
#define SSE_NUMERIC_OVERFLOW     0x400
#define SSE_NUMERIC_UNDERFLOW    0x800
#define SSE_INEXACT_RESULT      0x1000

short read_x87_control_register(void)
{
  short result;
  asm ("fstcw %0;"
       :"=m"(result));  
  return result;
}

void write_x87_control_register(short cw)
{
  asm ("fldcw %0;"
       : : "m"(cw));  
}

int read_sse_control_register(void)
{
  int result;
  asm ("stmxcsr %0;"
       :"=m"(result));  
  
  return result;
}

void write_sse_control_register(int csr)
{
  asm ("ldmxcsr %0;"
       : : "m"(csr));  
}

void enable_x87_exception(short mask) 
{
  short cw;
  cw = read_x87_control_register();
  cw &= ~mask;
  write_x87_control_register(cw);
}

void disable_x87_exception(short mask) 
{
  short cw;
  cw = read_x87_control_register();
  cw |= mask;
  write_x87_control_register(cw);
}

void enable_sse_exception(int mask) 
{
  int cw;
  cw = read_sse_control_register();
  cw &= ~mask;
  write_sse_control_register(cw);
}

void disable_sse_exception(int mask) 
{
  int cw;
  cw = read_sse_control_register();
  cw |= mask;
  write_sse_control_register(cw);
}

void enable_x87_invalid_operation_exception(void) {enable_x87_exception(X87_INVALID_OPERATION);}
void enable_x87_divide_by_zero_exception(void) {enable_x87_exception(X87_DIVIDE_BY_ZERO);}
void enable_x87_denormalized_operand_exception(void) {enable_x87_exception(X87_DENORMALIZED_OPERAND);}
void enable_x87_numeric_overflow_exception(void) {enable_x87_exception(X87_NUMERIC_OVERFLOW);}
void enable_x87_numeric_underflow_exception(void) {enable_x87_exception(X87_NUMERIC_UNDERFLOW);}
void enable_x87_inexact_result_exception(void) {enable_x87_exception(X87_INEXACT_RESULT);}

void disable_x87_invalid_operation_exception(void) {disable_x87_exception(X87_INVALID_OPERATION);}
void disable_x87_divide_by_zero_exception(void) {disable_x87_exception(X87_DIVIDE_BY_ZERO);}
void disable_x87_denormalized_operand_exception(void) {disable_x87_exception(X87_DENORMALIZED_OPERAND);}
void disable_x87_numeric_overflow_exception(void) {disable_x87_exception(X87_NUMERIC_OVERFLOW);}
void disable_x87_numeric_underflow_exception(void) {disable_x87_exception(X87_NUMERIC_UNDERFLOW);}
void disable_x87_inexact_result_exception(void) {disable_x87_exception(X87_INEXACT_RESULT);}

void enable_sse_invalid_operation_exception(void) {enable_sse_exception(SSE_INVALID_OPERATION);}
void enable_sse_divide_by_zero_exception(void) {enable_sse_exception(SSE_DIVIDE_BY_ZERO);}
void enable_sse_denormalized_operand_exception(void) {enable_sse_exception(SSE_DENORMALIZED_OPERAND);}
void enable_sse_numeric_overflow_exception(void) {enable_sse_exception(SSE_NUMERIC_OVERFLOW);}
void enable_sse_numeric_underflow_exception(void) {enable_sse_exception(SSE_NUMERIC_UNDERFLOW);}
void enable_sse_inexact_result_exception(void) {enable_sse_exception(SSE_INEXACT_RESULT);}

void disable_sse_invalid_operation_exception(void) {disable_sse_exception(SSE_INVALID_OPERATION);}
void disable_sse_divide_by_zero_exception(void) {disable_sse_exception(SSE_DIVIDE_BY_ZERO);}
void disable_sse_denormalized_operand_exception(void) {disable_sse_exception(SSE_DENORMALIZED_OPERAND);}
void disable_sse_numeric_overflow_exception(void) {disable_sse_exception(SSE_NUMERIC_OVERFLOW);}
void disable_sse_numeric_underflow_exception(void) {disable_sse_exception(SSE_NUMERIC_UNDERFLOW);}
void disable_sse_inexact_result_exception(void) {disable_sse_exception(SSE_INEXACT_RESULT);}

void enable_all_exceptions(void)
{
  // cursory error checking
  if (sizeof(short) != 2 || 
      sizeof(int) != 4)
    printf("Types not the expected size -- results may surpise you\n");

  enable_x87_invalid_operation_exception();
  enable_x87_divide_by_zero_exception();
  enable_x87_denormalized_operand_exception();
  enable_x87_numeric_overflow_exception();
  enable_x87_numeric_underflow_exception();
  enable_x87_inexact_result_exception();
  enable_sse_invalid_operation_exception();
  enable_sse_divide_by_zero_exception();
  enable_sse_denormalized_operand_exception();
  enable_sse_numeric_overflow_exception();
  enable_sse_numeric_underflow_exception();
  enable_sse_inexact_result_exception();
}

void disable_all_exceptions(void)
{
  disable_x87_invalid_operation_exception();
  disable_x87_divide_by_zero_exception();
  disable_x87_denormalized_operand_exception();
  disable_x87_numeric_overflow_exception();
  disable_x87_numeric_underflow_exception();
  disable_x87_inexact_result_exception();
  disable_sse_invalid_operation_exception();
  disable_sse_divide_by_zero_exception();
  disable_sse_denormalized_operand_exception();
  disable_sse_numeric_overflow_exception();
  disable_sse_numeric_underflow_exception();
  disable_sse_inexact_result_exception();
}

Answers/Code/IntelFloatingPointExceptionsDotC (last edited 2007-09-12 23:32:51 by GregNovak)