Quantcast
Channel: Nikolay Igotti
Viewing all articles
Browse latest Browse all 30

Fixing FPU control word on Win32

$
0
0
On Win32 fixing of control word is also possible, but done differently, as Win32 uses SEH (structured exception handlers) to handle hardware faults, and some magic is required to let fault really restart.
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <float.h>

long original_fpcw = 0;

LONG WINAPI exceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
    DWORD ec = exceptionInfo->ExceptionRecord->ExceptionCode; 
    if (ec == EXCEPTION_FLT_UNDERFLOW || ec == EXCEPTION_FLT_INEXACT_RESULT) {
	  PCONTEXT ctx = exceptionInfo->ContextRecord;
          // mask underflow, precision, invalid
          ctx->FloatSave.ControlWord = original_fpcw | 0xffff0031;
	  ctx->FloatSave.StatusWord &= ctx->FloatSave.ControlWord | 0xffffff80;
          return EXCEPTION_CONTINUE_EXECUTION;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}

int _tmain(int argc, _TCHAR* argv[]) 
{
__try {
       
        float d=0.1,v=1;
        int i;
        original_fpcw = _control87(0, 0);
        _control87(_EM_INEXACT, MCW_EM);

        for (i=0; i < 1000; i++) {
            v *= d;
        }
        printf("v = %0.60f\n",v);
    } __except(exceptionFilter(
               (_EXCEPTION_POINTERS*)GetExceptionInformation())) {
    }
    return 0;
}
PS: for references, FPU control word bits mean (fpu_control.h):
 *     15-13    12  11-10  9-8     7-6     5    4    3    2    1    0
 * | reserved | IC | RC  | PC | reserved | PM | UM | OM | ZM | DM | IM
 *
 * IM: Invalid operation mask
 * DM: Denormalized operand mask
 * ZM: Zero-divide mask
 * OM: Overflow mask
 * UM: Underflow mask
 * PM: Precision (inexact result) mask
 *
 * Mask bit is 1 means no interrupt.
 *
 * PC: Precision control
 * 11 - round to extended precision
 * 10 - round to double precision
 * 00 - round to single precision
 *
 * RC: Rounding control
 * 00 - rounding to nearest
 * 01 - rounding down (toward - infinity)
 * 10 - rounding up (toward + infinity)
 * 11 - rounding toward zero
 *
 *
 * IC: Infinity control
 * That is for 8087 and 80287 only.

Viewing all articles
Browse latest Browse all 30

Trending Articles