[git] CMU Common Lisp branch master updated. snapshot-2014-08-22-g2c4a13a

Raymond Toy rtoy at common-lisp.net
Fri Aug 22 04:56:35 UTC 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMU Common Lisp".

The branch, master has been updated
       via  2c4a13afde093c0e1eb415c7252efaad6ca362f5 (commit)
      from  33097329493c7a767bcc4434f3212badcb33236a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2c4a13afde093c0e1eb415c7252efaad6ca362f5
Author: Raymond Toy <toy.raymond at gmail.com>
Date:   Thu Aug 21 21:56:26 2014 -0700

    Re-enable the x87 floating-point mode stuff.
    
    On 32-bit linux, we can still get FP exceptions using x87 because
    32-bit linux can still use x87 instructions for arithmetic.  Because
    of this, we need to re-enable the support x87 floating-point modes,
    including getting and setting the modes and also extracting the modes
    from a sigcontext.
    
     * src/code/float-trap.lisp:
       * Put back support for getting and setting the x87 FP modes.
     * src/compiler/x86/float.lisp:
       * Add comment on the layout of the status and control words for
         x87.
     * src/lisp/Linux-os.c:
       * Put back support for getting the x87 (and sse2) FP modes. Needed
         in the sigfpe-handler in float-trap.lisp.
    
    Some of this needs to be cleaned up because we always require sse2
    now.

diff --git a/src/code/float-trap.lisp b/src/code/float-trap.lisp
index 7f27ffd..d97d04e 100644
--- a/src/code/float-trap.lisp
+++ b/src/code/float-trap.lisp
@@ -64,17 +64,62 @@
 (defun (setf floating-point-modes) (new) (setf (floating-point-modes) new))
 )
 
+#+(and x86 (not sse2))
+(progn
+  (defun floating-point-modes ()
+    (let ((x87-modes (vm::x87-floating-point-modes)))
+      ;; Massage the bits from x87-floating-point-modes into the order
+      ;; that the rest of the system wants them to be.  (Must match
+      ;; format in the SSE2 mxcsr register.)
+      (logior (ash (logand #x3f x87-modes) 7) ; control
+	      (logand #x3f (ash x87-modes -16)))))
+  (defun (setf floating-point-modes) (new)
+    (let* ((rc (ldb float-rounding-mode new))
+	   (x87-modes
+	    (logior (ash (logand #x3f new) 16)
+		    (ash rc 10)
+		    (logand #x3f (ash new -7))
+		    ;; Set precision control to be 53-bit, always.
+		    ;; (The compiler takes care of handling
+		    ;; single-float precision, and we don't support
+		    ;; long-floats.)
+		    (ash 2 8))))
+    (setf (x87-floating-point-modes) x87-modes)))
+  )
+
 #+sse2
 (progn
   (defun floating-point-modes ()
-    ;; Get just the SSE2 mode bits.
-    (vm::sse2-floating-point-modes))
+    ;; Combine the modes from the FPU and SSE2 units.  Since the sse
+    ;; mode contains all of the common information we want, we massage
+    ;; the x87-modes to match, and then OR the x87 and sse2 modes
+    ;; together.  Note: We ignore the rounding control bits from the
+    ;; FPU and only use the SSE2 rounding control bits.
+    (let* ((x87-modes (vm::x87-floating-point-modes))
+	   (sse-modes (vm::sse2-floating-point-modes))
+	   (final-mode (logior sse-modes
+			       (ash (logand #x3f x87-modes) 7) ; control
+			       (logand #x3f (ash x87-modes -16)))))
+
+      final-mode))
   (defun (setf floating-point-modes) (new-mode)
     (declare (type (unsigned-byte 24) new-mode))
-    ;; Set the floating point modes for SSE2.
-    (setf (vm::sse2-floating-point-modes) new-mode)
+    ;; Set the floating point modes for both X87 and SSE2.  This
+    ;; include the rounding control bits.
+    (let* ((rc (ldb float-rounding-mode new-mode))
+	   (x87-modes
+	    (logior (ash (logand #x3f new-mode) 16)
+		    (ash rc 10)
+		    (logand #x3f (ash new-mode -7))
+		    ;; Set precision control to be 64-bit, always.  We
+		    ;; don't use the x87 registers with sse2, so this
+		    ;; is ok and would be the correct setting if we
+		    ;; ever support long-floats.
+		    (ash 3 8))))
+      (setf (vm::sse2-floating-point-modes) new-mode)
+      (setf (vm::x87-floating-point-modes) x87-modes))
     new-mode)
-  )
+)
 
 ;;; SET-FLOATING-POINT-MODES  --  Public
 ;;;
diff --git a/src/compiler/x86/float.lisp b/src/compiler/x86/float.lisp
index a515e40..e617149 100644
--- a/src/compiler/x86/float.lisp
+++ b/src/compiler/x86/float.lisp
@@ -2303,6 +2303,43 @@
 (defknown ((setf x87-floating-point-modes)) (float-modes)
   float-modes)
 
+;; For the record, here is the format of the x86 FPU status word
+;;
+;; Bit
+;; 15       FPU Busy
+;; 14       C3 (condition code)
+;; 13-11    Top of stack
+;; 10       C2 (condition code)
+;;  9       C1 (condition code)
+;;  8       C0 (condition code)
+;;  7       Error summary status
+;;  6       Stack fault
+;;  5       precision flag (inexact)
+;;  4       underflow flag
+;;  3       overflow flag
+;;  2       divide-by-zero flag
+;;  1       denormalized operand flag
+;;  0       invalid operation flag
+;;
+;; When one of the flag bits (0-5) is set, then that exception has
+;; been detected since the bits were last cleared.
+;;
+;; The control word:
+;;
+;; 15-13    reserved
+;; 12       infinity control
+;; 11-10    rounding control
+;; 9-8      precision control
+;; 7-6      reserved
+;;  5       precision masked
+;;  4       underflow masked
+;;  3       overflow masked
+;;  2       divide-by-zero masked
+;;  1       denormal operand masked
+;;  0       invalid operation masked
+;;
+;; When one of the mask bits (0-5) is set, then that exception is
+;; masked so that no exception is generated.
 (define-vop (x87-floating-point-modes)
   (:results (res :scs (unsigned-reg)))
   (:result-types unsigned-num)
diff --git a/src/lisp/Linux-os.c b/src/lisp/Linux-os.c
index 2da60fb..7f7a4d7 100644
--- a/src/lisp/Linux-os.c
+++ b/src/lisp/Linux-os.c
@@ -217,13 +217,16 @@ os_sigcontext_fpu_reg(ucontext_t *scp, int offset)
     if (fpregs) {
         if (offset < 8) {
             reg = (unsigned char *) &fpregs->_st[offset];
-        } else if (offset < 16) {
+        }
+#ifdef FEATURE_SSE2
+        else {
             struct _fpstate *fpstate;
             fpstate = (struct _fpstate*) scp->uc_mcontext.fpregs;
             if (fpstate->magic != 0xffff) {
                 reg = (unsigned char *) &fpstate->_xmm[offset - 8];
             }
         }
+#endif
     }
     return reg;
 }
@@ -231,27 +234,39 @@ os_sigcontext_fpu_reg(ucontext_t *scp, int offset)
 unsigned int
 os_sigcontext_fpu_modes(ucontext_t *scp)
 {
-    unsigned int modes = 0;
-
-    /*
-     * Get the SSE2 modes.  FIXME: What should we do if the magic
-     * value indicates that the mxcsr value is not in the context?
-     */
-    struct _fpstate *fpstate;
-    unsigned long mxcsr;
+    unsigned int modes;
+    unsigned short cw, sw;
 
-    fpstate = (struct _fpstate*) scp->uc_mcontext.fpregs;
-    if (fpstate->magic == 0xffff) {
-        mxcsr = 0;
+    if (scp->uc_mcontext.fpregs == NULL) {
+	cw = 0;
+	sw = 0x3f;
     } else {
-        mxcsr = fpstate->mxcsr;
-        DPRINTF(0, (stderr, "SSE2 modes = %08lx\n", mxcsr));
+	cw = scp->uc_mcontext.fpregs->cw & 0xffff;
+	sw = scp->uc_mcontext.fpregs->sw & 0xffff;
     }
 
-    modes |= mxcsr;
+    modes = ((cw & 0x3f) << 7) | (sw & 0x3f);
+
+#ifdef FEATURE_SSE2
+    /*
+     * Add in the SSE2 part, if we're running the sse2 core.
+     */
+    if (fpu_mode == SSE2) {
+        struct _fpstate *fpstate;
+	unsigned long mxcsr;
+
+        fpstate = (struct _fpstate*) scp->uc_mcontext.fpregs;
+        if (fpstate->magic == 0xffff) {
+            mxcsr = 0;
+        } else {
+            mxcsr = fpstate->mxcsr;
+            DPRINTF(0, (stderr, "SSE2 modes = %08lx\n", mxcsr));
+        }
 
+	modes |= mxcsr;
+    }
+#endif
 
-    /* Convert exception mask to exception enable */
     modes ^= (0x3f << 7);
     return modes;
 }
@@ -528,19 +543,25 @@ void
 restore_fpu(ucontext_t *context)
 {
     if (context->uc_mcontext.fpregs) {
-        struct _fpstate *fpstate;
-        unsigned int mxcsr;
+	short cw = context->uc_mcontext.fpregs->cw;
+        DPRINTF(0, (stderr, "restore_fpu:  cw = %08x\n", cw));
+	__asm__ __volatile__ ("fldcw %0" : : "m" (*&cw));
+#ifdef FEATURE_SSE2
+        if (fpu_mode == SSE2) {
+            struct _fpstate *fpstate;
+            unsigned int mxcsr;
             
-        fpstate = (struct _fpstate*) context->uc_mcontext.fpregs;
-        if (fpstate->magic != 0xffff) {
-            mxcsr = fpstate->mxcsr;
-            DPRINTF(0, (stderr, "restore_fpu:  mxcsr (raw) = %04x\n", mxcsr));
-            __asm__ __volatile__ ("ldmxcsr %0" :: "m" (*&mxcsr));
+            fpstate = (struct _fpstate*) context->uc_mcontext.fpregs;
+            if (fpstate->magic != 0xffff) {
+                mxcsr = fpstate->mxcsr;
+                DPRINTF(0, (stderr, "restore_fpu:  mxcsr (raw) = %04x\n", mxcsr));
+                __asm__ __volatile__ ("ldmxcsr %0" :: "m" (*&mxcsr));
+            }
         }
+#endif        
     }
 }
 
-
 #ifdef i386
 boolean
 os_support_sse2()

-----------------------------------------------------------------------

Summary of changes:
 src/code/float-trap.lisp    |   55 ++++++++++++++++++++++++++++++----
 src/compiler/x86/float.lisp |   37 +++++++++++++++++++++++
 src/lisp/Linux-os.c         |   69 ++++++++++++++++++++++++++++---------------
 3 files changed, 132 insertions(+), 29 deletions(-)


hooks/post-receive
-- 
CMU Common Lisp



More information about the cmucl-cvs mailing list