[Openmcl-devel] Floating point exceptions on Windows
gb at clozure.com
Tue May 5 23:27:14 UTC 2009
For some reason, I didn't see the original message.
I also have to confess to being (willfully and otherwise) x87-ignorant,
so some of the details below m
x87 exceptions generally aren't precise, which means that they'll be
raised sometime after they occur (on some subsequent x87 instruction;
an "fwait" instruction waits for the x87 to actually bother to update
its status word to reflect the actual exception status of the chip.
This makes for a good theory: fn1() executes some sort of "fdiv" which
causes a divide-by-zero but doesn't update the status word. We return
from the call to fn1(), see no exception bits in the status word, and
chug merrily along. A subsequent call to log() does some x87 instruction
which (finally) causes the status word to be updated; we return from
the call to log, notice that the divide-by-zero bit is set, and report
That sounds like a good theory, but it may not be a correct one: I'm
fairly sure that we'd want to use MMX instructions between the return
from fn1() and the call to log(), and my (too lazy to RTFM) model of
how the x87 and MMX try to coexist is that using MMX basically clears
x87 state. (If that's not correct, or if the x87 status word is
preserved, then the theory's still good.)
If there's at least something to the theory, then it seems that we want
to change .SPffcall to:
- if we believe that the foreign code will use x87 math operations,
ensure that the x87 status word is zeroed before the call. (We
may not have to do anything explicit here.)
- on return from the call, if we think that the x87 might have been
involved, do the right flavor of "fwait" before reading the status
word and putting its value where lisp can find it. If we can tell
that any exception bits might have been set, zero the x87 status
register. If we can convince ourselves that lisp's incidental use
of the x87 can never cause an exception bit to be set, then zeroing
the status register here might be enough to ensure that it's always
zero on entry to the foreign code.
On Tue, 5 May 2009, R. Matthew Emerson wrote:
> On May 3, 2009, at 11:18 AM, Martin wrote:
>> I am using CCL 1.3-r11949 on Windows XP SP2 and have a problem with
>> floating point exception propagation.
>> Now, I have a file app1.c with a function with the following code
>> __declspec(dllexport) double fn1 ()
>> double zero = 0;
>> return 1.0/zero;
>> I compiled it into a DLL (Using MS Visual C++ 2005 Express Edition)
>> the following command:
>> cl /LD app1.c
>> to yield app1.dll.
>> Using it in CCL:
>> Welcome to Clozure Common Lisp Version 1.3-r11949M (WindowsX8632)!
>> ? (open-shared-library "D:/studies/floats/app1/app1.dll")
>> #<SHLIB app1.dll #x89DED5E>
>> ? (ff-call (%reference-external-entry-point (external
>> "fn1")) :double-float)
>> ? (log 10)
>>> Error: DIVISION-BY-ZERO detected
>>> performing LOG on (10.0)
>>> While executing: CCL::%FP-ERROR-FROM-STATUS, in process listener(1).
>>> Type :POP to abort, :R for a list of available restarts.
>>> Type :? for other options.
>> 1 >
> This is kind of a long shot, but...if you disassemble fn1(), does it
> use x87 or SSE2 instructions?
> On non-Darwin x8632 systems (including Windows), we assume that
> foreign code will use the x87 for floating-point operations. After
> the ff-call, we therefore will look at the x87 state to see if the
> foreign code signaled any fp exceptions. If the foreign code uses
> SS2E, we won't notice any exceptiopns (because we're looking for them
> in the wrong place: the x87 state, and not the mxcsr).
>> 2. How can I disable floating point exceptions from within CCL?
> The manual documents SET-FPU-MODE and GET-FPU-MODE, which will let you
> do this.
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
More information about the Openmcl-devel