The branch "master" has been updated in SBCL:
via f60e9933a652a3b6ff5d3176f85a41833c1bc338 (commit)
from 987e39e16c89c33f163f8f2d85cc28f67738d67d (commit)
- Log -----------------------------------------------------------------
commit f60e9933a652a3b6ff5d3176f85a41833c1bc338
Author: Alastair Bridgewater <nyef@...>
Date: Sun Oct 23 22:36:24 2011 -0400
Fix FP traps on OSX/x86-64.
* De-cripple SB-INT:SET-FLOATING-POINT-MODES for this platform.
* Enable restoring the FPU control word during interrupt handling
on this platform (RESTORE_FP_CONTROL_FROM_CONTEXT).
* Implement restoring the FPU control word on this platform
(os_restore_fp_control).
* Update :FAILS-ON information for the now-passing tests.
* Insert an addtional copy of test float.pure.lisp /
(ADDITION-OVERFLOW BUG-372) to detect failure to restore the FPU
control word in signal handling, with appropriate commentary.
---
NEWS | 1 +
src/code/float-trap.lisp | 3 ++-
src/runtime/x86-64-darwin-os.c | 18 ++++++++++++++++++
src/runtime/x86-64-darwin-os.h | 3 +++
tests/float.pure.lisp | 25 +++++++++++++++++++++++--
5 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 5393949..b141253 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ changes relative to sbcl-1.0.52:
GETF, LOGBITP, LDB, and MASK-FIELD now arrange for non-primary values
of multiple-valued places to be set to NIL, instead of signalling an
error (per a careful reading of CLHS 5.1.2.3).
+ * bug fix: floating-point traps now work on darwin/x86-64.
changes in sbcl-1.0.52 relative to sbcl-1.0.51:
* enhancement: ASDF has been updated to version 2.017.
diff --git a/src/code/float-trap.lisp b/src/code/float-trap.lisp
index 4bd83cb..86f402e 100644
--- a/src/code/float-trap.lisp
+++ b/src/code/float-trap.lisp
@@ -118,7 +118,8 @@ in effect."
(or (cdr (assoc precision *precision-mode-alist*))
(error "unknown precision mode: ~S" precision))))
;; FIXME: This apparently doesn't work on Darwin
- #!-darwin (setf (floating-point-modes) modes))
+ #!-(and darwin (or ppc x86))
+ (setf (floating-point-modes) modes))
(values))
(defun get-floating-point-modes ()
diff --git a/src/runtime/x86-64-darwin-os.c b/src/runtime/x86-64-darwin-os.c
index 180db11..86d4687 100644
--- a/src/runtime/x86-64-darwin-os.c
+++ b/src/runtime/x86-64-darwin-os.c
@@ -49,6 +49,9 @@ typedef struct __darwin_mcontext64 darwin_mcontext;
#define es __es
#define fs __fs
+#define fpu_fcw __fpu_fcw
+#define fpu_mxcsr __fpu_mxcsr
+
#else
typedef struct ucontext darwin_ucontext;
@@ -587,4 +590,19 @@ catch_exception_raise(mach_port_t exception_port,
return ret;
}
+void
+os_restore_fp_control(os_context_t *context)
+{
+ /* KLUDGE: The x87 FPU control word is some nasty bitfield struct
+ * thing. Rather than deal with that, just grab it as a 16-bit
+ * integer. */
+ unsigned short fpu_control_word =
+ *((unsigned short *)&context->uc_mcontext->fs.fpu_fcw);
+ /* reset exception flags and restore control flags on SSE2 FPU */
+ unsigned int temp = (context->uc_mcontext->fs.fpu_mxcsr) & ~0x3F;
+ asm ("ldmxcsr %0" : : "m" (temp));
+ /* same for x87 FPU. */
+ asm ("fldcw %0" : : "m" (fpu_control_word));
+}
+
#endif
diff --git a/src/runtime/x86-64-darwin-os.h b/src/runtime/x86-64-darwin-os.h
index 22cde5e..53b2230 100644
--- a/src/runtime/x86-64-darwin-os.h
+++ b/src/runtime/x86-64-darwin-os.h
@@ -16,4 +16,7 @@ static inline os_context_t *arch_os_get_context(void **void_context)
#define CONTEXT_ADDR_FROM_STEM(stem) &context->uc_mcontext->ss.stem
#endif /* __DARWIN_UNIX03 */
+#define RESTORE_FP_CONTROL_FROM_CONTEXT
+void os_restore_fp_control(os_context_t *context);
+
#endif /* _X86_64_DARWIN_OS_H */
diff --git a/tests/float.pure.lisp b/tests/float.pure.lisp
index 60b3a36..a7d8e34 100644
--- a/tests/float.pure.lisp
+++ b/tests/float.pure.lisp
@@ -93,7 +93,7 @@
(assert (= 0.0d0 (scale-float 1.0d0 (1- most-negative-fixnum))))
(with-test (:name (:scale-float-overflow :bug-372)
- :fails-on :darwin) ;; bug 372
+ :fails-on '(and :darwin (or :ppc :x86))) ;; bug 372
(progn
(assert (raises-error? (scale-float 1.0 most-positive-fixnum)
floating-point-overflow))
@@ -125,7 +125,28 @@
(funcall (compile nil '(lambda () (tan (tan (round 0))))))
(with-test (:name (:addition-overflow :bug-372)
- :fails-on '(or (and :ppc :openbsd) :darwin (and :x86 :netbsd)))
+ :fails-on '(or (and :ppc :openbsd)
+ (and (or :ppc :x86) :darwin)
+ (and :x86 :netbsd)))
+ (assert (typep (nth-value
+ 1
+ (ignore-errors
+ (sb-sys:without-interrupts
+ (sb-int:set-floating-point-modes :current-exceptions nil
+ :accrued-exceptions nil)
+ (loop repeat 2 summing most-positive-double-float)
+ (sleep 2))))
+ 'floating-point-overflow)))
+
+;; This is the same test as above. Even if the above copy passes,
+;; this copy will fail if SIGFPE handling ends up clearing the FPU
+;; control word, which can happen if the kernel clears the FPU control
+;; (a reasonable thing for it to do) and the runtime fails to
+;; compensate for this (see RESTORE_FP_CONTROL_WORD in interrupt.c).
+(with-test (:name (:addition-overflow :bug-372 :take-2)
+ :fails-on '(or (and :ppc :openbsd)
+ (and (or :ppc :x86) :darwin)
+ (and :x86 :netbsd)))
(assert (typep (nth-value
1
(ignore-errors
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL
|