summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fenv/i386/fenv.s39
-rw-r--r--src/fenv/x86_64/fenv.s26
2 files changed, 38 insertions, 27 deletions
diff --git a/src/fenv/i386/fenv.s b/src/fenv/i386/fenv.s
index 9bba40a5..a8540add 100644
--- a/src/fenv/i386/fenv.s
+++ b/src/fenv/i386/fenv.s
@@ -4,26 +4,41 @@
.type feclearexcept,@function
feclearexcept:
mov 4(%esp),%ecx
- not %ecx
+ fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability
call 1f
1: addl $__hwcap-1b,(%esp)
pop %edx
testl $0x02000000,(%edx)
+ jz 2f
+ # maintain exceptions in the sse mxcsr, clear x87 exceptions
+ test %eax,%ecx
jz 1f
- stmxcsr 4(%esp)
- and %ecx,4(%esp)
- ldmxcsr 4(%esp)
-1: test $0x3f,%ecx
- jnz 2f
-1: fnclex
- xor %eax,%eax
+ fnclex
+1: push %edx
+ stmxcsr (%esp)
+ pop %edx
+ and $0x3f,%eax
+ or %eax,%edx
+ test %edx,%ecx
+ jz 1f
+ not %ecx
+ and %ecx,%edx
+ push %edx
+ ldmxcsr (%esp)
+ pop %edx
+1: xor %eax,%eax
ret
-2: fnstsw %ax
- # TODO: only load/store fenv if exceptions arent clear yet
- and %ecx,%eax
+ # only do the expensive x87 fenv load/store when needed
+2: test %eax,%ecx
jz 1b
- sub $32,%esp
+ not %ecx
+ and %ecx,%eax
+ test $0x3f,%eax
+ jz 1f
+ fnclex
+ jmp 1b
+1: sub $32,%esp
fnstenv (%esp)
mov %al,4(%esp)
fldenv (%esp)
diff --git a/src/fenv/x86_64/fenv.s b/src/fenv/x86_64/fenv.s
index c48dade3..dda6b61a 100644
--- a/src/fenv/x86_64/fenv.s
+++ b/src/fenv/x86_64/fenv.s
@@ -1,25 +1,21 @@
.global feclearexcept
.type feclearexcept,@function
feclearexcept:
+ # maintain exceptions in the sse mxcsr, clear x87 exceptions
mov %edi,%ecx
+ fnstsw %ax
+ test %eax,%ecx
+ jz 1f
+ fnclex
+1: stmxcsr -8(%rsp)
+ and $0x3f,%eax
+ or %eax,-8(%rsp)
+ test %ecx,-8(%rsp)
+ jz 1f
not %ecx
- stmxcsr -8(%rsp)
and %ecx,-8(%rsp)
ldmxcsr -8(%rsp)
- test $0x3f,%ecx
- jnz 2f
-1: fnclex
- xor %eax,%eax
- ret
-2: fnstsw %ax
- and %ecx,%eax
- jz 1b
- sub $32,%rsp
- fnstenv (%rsp)
- mov %al,4(%rsp)
- fldenv (%rsp)
- add $32,%rsp
- xor %eax,%eax
+1: xor %eax,%eax
ret
.global feraiseexcept