summaryrefslogtreecommitdiffstats
path: root/lib/libc/amd64
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2008-06-28 17:55:43 +0000
committerdas <das@FreeBSD.org>2008-06-28 17:55:43 +0000
commit610bd747b7bcb7c261f797b98f48478d9994781e (patch)
tree50753ee5022fdb7c1e8a537550b00e2c80532b21 /lib/libc/amd64
parent8f779d35ce6bfd2d82fb53ce57f2cb1161c87507 (diff)
downloadFreeBSD-src-610bd747b7bcb7c261f797b98f48478d9994781e.zip
FreeBSD-src-610bd747b7bcb7c261f797b98f48478d9994781e.tar.gz
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.
Diffstat (limited to 'lib/libc/amd64')
-rw-r--r--lib/libc/amd64/gen/_setjmp.S11
-rw-r--r--lib/libc/amd64/gen/setjmp.S11
2 files changed, 20 insertions, 2 deletions
diff --git a/lib/libc/amd64/gen/_setjmp.S b/lib/libc/amd64/gen/_setjmp.S
index 3998fbe..5d57f88 100644
--- a/lib/libc/amd64/gen/_setjmp.S
+++ b/lib/libc/amd64/gen/_setjmp.S
@@ -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
diff --git a/lib/libc/amd64/gen/setjmp.S b/lib/libc/amd64/gen/setjmp.S
index 7d11384..995c801 100644
--- a/lib/libc/amd64/gen/setjmp.S
+++ b/lib/libc/amd64/gen/setjmp.S
@@ -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
OpenPOWER on IntegriCloud