diff --git a/vm/os-windows-nt.32.hpp b/vm/os-windows-nt.32.hpp old mode 100644 new mode 100755 index ed67e28b8b..748272ff38 --- a/vm/os-windows-nt.32.hpp +++ b/vm/os-windows-nt.32.hpp @@ -4,4 +4,33 @@ namespace factor #define ESP Esp #define EIP Eip +typedef struct DECLSPEC_ALIGN(16) _M128A { + ULONGLONG Low; + LONGLONG High; +} M128A, *PM128A; + +/* The ExtendedRegisters field of the x86.32 CONTEXT structure uses this layout; however, + * this structure is only made available from winnt.h on x86.64 */ +typedef struct _XMM_SAVE_AREA32 { + WORD ControlWord; /* 000 */ + WORD StatusWord; /* 002 */ + BYTE TagWord; /* 004 */ + BYTE Reserved1; /* 005 */ + WORD ErrorOpcode; /* 006 */ + DWORD ErrorOffset; /* 008 */ + WORD ErrorSelector; /* 00c */ + WORD Reserved2; /* 00e */ + DWORD DataOffset; /* 010 */ + WORD DataSelector; /* 014 */ + WORD Reserved3; /* 016 */ + DWORD MxCsr; /* 018 */ + DWORD MxCsr_Mask; /* 01c */ + M128A FloatRegisters[8]; /* 020 */ + M128A XmmRegisters[16]; /* 0a0 */ + BYTE Reserved4[96]; /* 1a0 */ +} XMM_SAVE_AREA32, *PXMM_SAVE_AREA32; + +#define X87SW(ctx) (ctx)->FloatSave.StatusWord +#define MXCSR(ctx) ((XMM_SAVE_AREA32*)((ctx)->ExtendedRegisters))->MxCsr + } diff --git a/vm/os-windows-nt.64.hpp b/vm/os-windows-nt.64.hpp old mode 100644 new mode 100755 index 30ce150754..b64bd607cb --- a/vm/os-windows-nt.64.hpp +++ b/vm/os-windows-nt.64.hpp @@ -4,4 +4,7 @@ namespace factor #define ESP Rsp #define EIP Rip +#define X87SW(ctx) (ctx)->FloatSave.StatusWord +#define MXCSR(ctx) (ctx)->MxCsr + } diff --git a/vm/os-windows-nt.cpp b/vm/os-windows-nt.cpp old mode 100644 new mode 100755 index 017a96bb7c..b50c9b7af8 --- a/vm/os-windows-nt.cpp +++ b/vm/os-windows-nt.cpp @@ -28,16 +28,18 @@ FACTOR_STDCALL LONG exception_handler(PEXCEPTION_POINTERS pe) c->EIP = (cell)memory_signal_handler_impl; break; - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_INVALID_OPERATION: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_STACK_CHECK: - case EXCEPTION_FLT_UNDERFLOW: - /* XXX MxCsr is not available in CONTEXT structure on x86.32 */ - signal_fpu_status = c->FloatSave.StatusWord; - c->FloatSave.StatusWord = 0; + case STATUS_FLOAT_DENORMAL_OPERAND: + case STATUS_FLOAT_DIVIDE_BY_ZERO: + case STATUS_FLOAT_INEXACT_RESULT: + case STATUS_FLOAT_INVALID_OPERATION: + case STATUS_FLOAT_OVERFLOW: + case STATUS_FLOAT_STACK_CHECK: + case STATUS_FLOAT_UNDERFLOW: + case STATUS_FLOAT_MULTIPLE_FAULTS: + case STATUS_FLOAT_MULTIPLE_TRAPS: + signal_fpu_status = fpu_status(X87SW(c) | MXCSR(c)); + X87SW(c) = 0; + MXCSR(c) &= 0xffffffc0; c->EIP = (cell)fp_signal_handler_impl; break; case 0x40010006: diff --git a/vm/os-windows-nt.hpp b/vm/os-windows-nt.hpp old mode 100644 new mode 100755 index 4371771c13..088103bb5b --- a/vm/os-windows-nt.hpp +++ b/vm/os-windows-nt.hpp @@ -23,4 +23,9 @@ void c_to_factor_toplevel(cell quot); FACTOR_STDCALL LONG exception_handler(PEXCEPTION_POINTERS pe); void open_console(); +// SSE traps raise these exception codes, which are defined in internal NT headers +// but not winbase.h +#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4 +#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5 + }