From 5efbe3647f0cb0f30c32d36f784cc3fc314770c6 Mon Sep 17 00:00:00 2001 From: rtoy <rtoy> Date: Thu, 1 Apr 2010 14:05:45 +0000 Subject: [PATCH] Fix SSE2 bug when running (defun testfn () (let* ((i-gc-ed-u nil) (ext:*gc-notify-before* (lambda (a) (/ a 0.34d0)))) (dotimes (i 100000) (setf i-gc-ed-u nil) (let* ((v1 (list (* 1d0 (random 10)) (* 1d0 (random 10)))) (v2 (list (* 1d0 (random 10)) (* 1d0 (random 10)))) (dot1 (reduce #'+ (mapcar #'* v1 v2))) (dot2 (reduce #'+ (mapcar #'* v1 v2)))) (when (/= dot1 dot2) (print `(gc ,i-gc-ed-u v1 ,v1 v2 ,v2 dot1 ,dot1 dot2 ,dot2))))))) Running this with sse2 would cuase dot1 and dot2 to sometimes be different. We forgot to save the SSE2 state in call_into_lisp. (This bug was mentioned on comp.lang.lisp, http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/828371aa4800272c?hl=en# x86-assem.S: o Save and restore SSE2 state when running with SSE2 core. (This might need more tweaking. Should we use cpuid instead of looking at fpu_mode?) gencgc.c: o Save the SSE2 state, along with X87 state for SSE2 cores. --- lisp/gencgc.c | 20 ++++++++++++++++++-- lisp/x86-assem.S | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/lisp/gencgc.c b/lisp/gencgc.c index 6decb167b..11703d9ca 100644 --- a/lisp/gencgc.c +++ b/lisp/gencgc.c @@ -7,7 +7,7 @@ * * Douglas Crosher, 1996, 1997, 1998, 1999. * - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.106 2009/12/21 11:36:43 rswindells Exp $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/gencgc.c,v 1.107 2010/04/01 14:05:45 rtoy Exp $ * */ @@ -662,7 +662,14 @@ print_generation_stats(int verbose) #if defined(i386) || defined(__x86_64) #define FPU_STATE_SIZE 27 + /* + * Need 512 byte area, aligned on a 16-byte boundary. So allocate + * 512+16 bytes of space and let the routine adjust use the + * appropriate alignment. + */ +#define SSE_STATE_SIZE ((512+16)/4) int fpu_state[FPU_STATE_SIZE]; + int sse_state[SSE_STATE_SIZE]; #elif defined(sparc) /* * 32 (single-precision) FP registers, and the FP state register. @@ -683,7 +690,11 @@ print_generation_stats(int verbose) */ fpu_save(fpu_state); - +#if defined(i386) || defined(__x86_64) + if (fpu_mode == SSE2) { + sse_save(sse_state); + } +#endif /* Number of generations to print out. */ if (verbose) @@ -738,6 +749,11 @@ print_generation_stats(int verbose) fprintf(stderr, " Total bytes alloc=%ld\n", bytes_allocated); fpu_restore(fpu_state); +#if defined(i386) || defined(__x86_64) + if (fpu_mode == SSE2) { + sse_restore(sse_state); + } +#endif } /* Get statistics that are kept "on the fly" out of the generation diff --git a/lisp/x86-assem.S b/lisp/x86-assem.S index 8e3819c5b..f1c1e3d37 100644 --- a/lisp/x86-assem.S +++ b/lisp/x86-assem.S @@ -1,6 +1,6 @@ ### x86-assem.S -*- Mode: Asm; -*- /** - * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/x86-assem.S,v 1.32 2008/12/24 04:36:40 rtoy Rel $ + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/x86-assem.S,v 1.33 2010/04/01 14:05:45 rtoy Exp $ * * Authors: Paul F. Werkowski <pw@snoopy.mv.com> * Douglas T. Crosher @@ -134,9 +134,22 @@ FUNCDEF(call_into_lisp) /* Save the NPX state */ fwait # Catch any pending NPX exceptions. + /* Save the SSE2 for X87 state */ + mov GNAME(fpu_mode), %eax + cmp $2, %eax # SSE2 mode? + jne x87_save + movl %esp, %eax # Remember the current stack pointer + subl $512,%esp # Make room for the SSE state + andl $-16, %esp # fxsave needs 16-byte alignment + fxsave (%esp) + pushl %eax # Save the old stack pointer + fninit # Reset fpu, just in case + jmp npx_save_done + +x87_save: subl $108,%esp # Make room for the NPX state. fnsave (%esp) # Resets NPX - + movl (%esp),%eax # Load NPX control word andl $0xfffff3ff,%eax # Set rounding mode to nearest #ifdef type_LongFloat @@ -147,6 +160,7 @@ FUNCDEF(call_into_lisp) pushl %eax fldcw (%esp) # Recover modes popl %eax +npx_save_done: fldz # insure no FP regs are empty fldz @@ -224,9 +238,19 @@ Ldone: popl %ebx /* Restore the NPX state */ + /* Restore SSE2 state? */ + mov GNAME(fpu_mode), %eax + cmp $2, %eax # SSE2 mode? + jne x87_restore + popl %eax # Get the old stack pointer + fxrstor (%esp) # Restore the SSE state + movl %eax, %esp # Now really restore the old stack pointer + jmp npx_restore_done +x87_restore: frstor (%esp) addl $108, %esp - +npx_restore_done: + popl %ebp # c-sp movl %edx,%eax # c-val ret @@ -244,6 +268,22 @@ FUNCDEF(fpu_restore) frstor (%eax) # Restore the NPX state. ret ENDFUNC(fpu_restore) + +FUNCDEF(sse_save) + movl 4(%esp),%eax + addl $16, %eax # Make sure eax is on a 16-byte boundary + and $-16, %eax + fxsave (%eax) + ret +ENDFUNC(sse_save) + +FUNCDEF(sse_restore) + movl 4(%esp),%eax + addl $16, %eax # Make sure eax is on a 16-byte boundary + and $-16, %eax + fxrstor (%eax) + ret +ENDFUNC(sse_restore) /* -- GitLab