Index: /branches/rme-fpe/lisp-kernel/x86-exceptions.c
===================================================================
--- /branches/rme-fpe/lisp-kernel/x86-exceptions.c	(revision 13936)
+++ /branches/rme-fpe/lisp-kernel/x86-exceptions.c	(revision 13937)
@@ -942,5 +942,5 @@
 
 Boolean
-handle_floating_point_exception(TCR *tcr, ExceptionInformation *xp, siginfo_t *info)
+handle_floating_point_exception(TCR *tcr, ExceptionInformation *xp, siginfo_t *info, int old_valence)
 {
   int code,skip;
@@ -954,6 +954,23 @@
 #endif  
 
-  if ((fulltag_of(cmain) == fulltag_misc) &&
-      (header_subtag(header_of(cmain)) == subtag_macptr)) {
+  if (old_valence == TCR_STATE_FOREIGN) {
+    /* We got a floating point exception in foreign code.  Set a flag
+       in the TCR to indicate this, and resume with FP exceptions
+       disabled.  .SPffcall will check the flag, and if it's set,
+       will save the FP status and re-enable exceptions. */
+
+    /*
+     * We might get multiple foreign FP exceptions, so take care
+     * to preseve lisp's original MXCSR.
+     */
+    if (! (tcr->flags & (1<<TCR_FLAG_BIT_FOREIGN_FPE))) {
+      tcr->lisp_mxcsr = xpMXCSR(xp) & ~MXCSR_STATUS_MASK;
+      tcr->flags |= (1<<TCR_FLAG_BIT_FOREIGN_FPE);
+    }
+    xpMXCSR(xp) &= ~MXCSR_STATUS_MASK;
+    xpMXCSR(xp) |= MXCSR_CONTROL_MASK;
+    return true;
+  } else if ((fulltag_of(cmain) == fulltag_misc) &&
+	     (header_subtag(header_of(cmain)) == subtag_macptr)) {
     xcf = create_exception_callback_frame(xp, tcr);
     skip = callback_to_lisp(tcr, cmain, xp, xcf, SIGFPE, code, 0, 0);
@@ -1078,5 +1095,5 @@
   pc program_counter = (pc)xpPC(context);
 
-  if (old_valence != TCR_STATE_LISP) {
+  if ((old_valence != TCR_STATE_LISP) && signum != SIGFPE) {
     return false;
   }
@@ -1237,5 +1254,5 @@
 #endif
 
-    return handle_floating_point_exception(tcr, context, info);
+    return handle_floating_point_exception(tcr, context, info, old_valence);
 
 #if SIGBUS != SIGNUM_FOR_INTN_TRAP
Index: /branches/rme-fpe/lisp-kernel/x86-spentry32.s
===================================================================
--- /branches/rme-fpe/lisp-kernel/x86-spentry32.s	(revision 13936)
+++ /branches/rme-fpe/lisp-kernel/x86-spentry32.s	(revision 13937)
@@ -4184,7 +4184,5 @@
 	__(popl rcontext(tcr.save_eflags))
 	__(cld)        
-	__(stmxcsr rcontext(tcr.lisp_mxcsr))
 	__(emms)
-	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
 	__(movl (%esp),%ebp)
 LocalLabelPrefix`'ffcall_setup:
@@ -4215,4 +4213,9 @@
 	__(clr %fn)
 	__(pxor %fpzero,%fpzero)
+	/* If we got a floating-point exception during the ff-call,
+	   our handler will have set a flag, preserved lisp's MXCSR,
+	   and resumed execution with fp exceptions masked. */
+	__(btrq $TCR_FLAG_BIT_FOREIGN_FPE,rcontext(tcr.flags))
+	__(jnc 1f)
 	__(cmpb $0,C(bogus_fp_exceptions))
 	__(je 0f)
@@ -4222,4 +4225,5 @@
 	__ifdef(`SSE2_MATH_LIB')
 	__(stmxcsr rcontext(tcr.ffi_exception))
+       	__(ldmxcsr rcontext(tcr.lisp_mxcsr)) /* preserved by the handler */
 	__else
 	__(fnstsw rcontext(tcr.ffi_exception))
@@ -4235,5 +4239,4 @@
         __(pop %arg_y) 	 	 
         __(pop %temp1) 
-       	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
 	__(check_pending_interrupt(%temp0))
         __(pop %temp0)
Index: /branches/rme-fpe/lisp-kernel/x86-spentry64.s
===================================================================
--- /branches/rme-fpe/lisp-kernel/x86-spentry64.s	(revision 13936)
+++ /branches/rme-fpe/lisp-kernel/x86-spentry64.s	(revision 13937)
@@ -3991,7 +3991,5 @@
 	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
         __(movq rcontext(tcr.foreign_sp),%rsp)
-	__(stmxcsr rcontext(tcr.lisp_mxcsr))
 	__(emms)
-	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
 	__(movq (%rsp),%rbp)
         __ifdef(`DARWIN_GS_HACK')
@@ -4070,4 +4068,10 @@
 	__(clr %fn)
 	__(pxor %fpzero,%fpzero)
+
+	/* If we got a floating-point exception during the ff-call,
+	   our handler will have set a flag, preserved lisp's MXCSR,
+	   and resumed execution with fp exceptions masked. */
+	__(btrq $TCR_FLAG_BIT_FOREIGN_FPE,rcontext(tcr.flags))
+	__(jnc 1f)
         __(cmpb $0,C(bogus_fp_exceptions)(%rip))
         __(je 0f)
@@ -4075,4 +4079,5 @@
         __(jmp 1f)
 0:      __(stmxcsr rcontext(tcr.ffi_exception))
+	__(ldmxcsr rcontext(tcr.lisp_mxcsr)) /* preserved by the handler */
 1:      __(movq rcontext(tcr.save_vsp),%rsp)
         __(movq rcontext(tcr.save_rbp),%rbp)
@@ -4090,5 +4095,4 @@
 	__(pop %temp2)
 	__(pop %temp1)
-	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
 	__(check_pending_interrupt(%temp0))
 	__(pop %temp0)
@@ -4211,7 +4215,5 @@
 	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
         __(movq rcontext(tcr.foreign_sp),%rsp)
-	__(stmxcsr rcontext(tcr.lisp_mxcsr))
 	__(emms)
-	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
 	__(movq (%rsp),%rbp)
         __ifdef(`DARWIN_GS_HACK')
@@ -4290,4 +4292,7 @@
 	__(clr %fn)
 	__(pxor %fpzero,%fpzero)
+	/* Check for fp exceptions as in .SPffcall, above. */
+	__(btrq $TCR_FLAG_BIT_FOREIGN_FPE,rcontext(tcr.flags))
+	__(jnc 1f)
         __(cmpb $0,C(bogus_fp_exceptions)(%rip))
         __(je 0f)
@@ -4295,4 +4300,5 @@
         __(jmp 1f)
 0:      __(stmxcsr rcontext(tcr.ffi_exception))
+	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
 1:      __(movq rcontext(tcr.save_vsp),%rsp)
         __(movq rcontext(tcr.save_rbp),%rbp)
@@ -4310,5 +4316,4 @@
 	__(pop %temp2)
 	__(pop %temp1)
-	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
 	__(check_pending_interrupt(%temp0))
 	__(pop %temp0)
