Two FP-related setjmp/longjmp changes:

1. Save and restore the control part of the MXCSR in addition to the
   i387 control word to ensure that the two are consistent.

   Note that standards don't require longjmp to restore either control
   word, and none of Linux, MacOS X 10.3 and earlier, NetBSD, OpenBSD,
   or Solaris do it. However, it is historical FreeBSD behavior, and
   bde points out that it is needed to make longjmping out of a signal
   handler work properly, given the way FreeBSD clobbers the FPU state
   on signal handler entry.

2. Don't clobber the FPU exception flags in longjmp. C99 requires them
   to remain unchanged.
This commit is contained in:
David Schultz 2008-06-28 17:55:43 +00:00
parent b370e2cfea
commit 64c2e46650
2 changed files with 20 additions and 2 deletions

View File

@ -58,6 +58,7 @@ ENTRY(_setjmp)
movq %r14,48(%rax) /* 6; r14 */
movq %r15,56(%rax) /* 7; r15 */
fnstcw 64(%rax) /* 8; fpu cw */
stmxcsr 68(%rax) /* and mxcsr */
xorq %rax,%rax
ret
@ -65,6 +66,15 @@ ENTRY(_setjmp)
.set CNAME(_longjmp),CNAME(___longjmp)
ENTRY(___longjmp)
movq %rdi,%rdx
/* Restore the mxcsr, but leave exception flags intact. */
stmxcsr -4(%rsp)
movl 68(%rdx),%eax
andl $0xffffffc0,%eax
movl -4(%rsp),%edi
andl $0x3f,%edi
xorl %eax,%edi
movl %edi,-4(%rsp)
ldmxcsr -4(%rsp)
movq %rsi,%rax /* retval */
movq 0(%rdx),%rcx
movq 8(%rdx),%rbx
@ -74,7 +84,6 @@ ENTRY(___longjmp)
movq 40(%rdx),%r13
movq 48(%rdx),%r14
movq 56(%rdx),%r15
fninit
fldcw 64(%rdx)
testq %rax,%rax
jnz 1f

View File

@ -67,6 +67,7 @@ ENTRY(setjmp)
movq %r14,48(%rcx) /* 6; r14 */
movq %r15,56(%rcx) /* 7; r15 */
fnstcw 64(%rcx) /* 8; fpu cw */
stmxcsr 68(%rcx) /* and mxcsr */
xorq %rax,%rax
ret
@ -83,6 +84,15 @@ ENTRY(__longjmp)
popq %rsi
popq %rdi /* jmpbuf */
movq %rdi,%rdx
/* Restore the mxcsr, but leave exception flags intact. */
stmxcsr -4(%rsp)
movl 68(%rdx),%eax
andl $0xffffffc0,%eax
movl -4(%rsp),%edi
andl $0x3f,%edi
xorl %eax,%edi
movl %edi,-4(%rsp)
ldmxcsr -4(%rsp)
movq %rsi,%rax /* retval */
movq 0(%rdx),%rcx
movq 8(%rdx),%rbx
@ -92,7 +102,6 @@ ENTRY(__longjmp)
movq 40(%rdx),%r13
movq 48(%rdx),%r14
movq 56(%rdx),%r15
fninit
fldcw 64(%rdx)
testq %rax,%rax
jnz 1f