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.