make thread list lock a recursive lock
[musl] / src / fenv / i386 / fenv.s
index e365b8f..e7f7932 100644 (file)
@@ -1,17 +1,45 @@
+.hidden __hwcap
+
 .global feclearexcept
 .type feclearexcept,@function
 feclearexcept: 
        mov 4(%esp),%ecx
+       and $0x3f,%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
+       fnclex
+1:     push %edx
+       stmxcsr (%esp)
+       pop %edx
+       and $0x3f,%eax
+       or %eax,%edx
+       test %edx,%ecx
+       jz 1f
        not %ecx
-       test $0x3f,%ecx
-       jnz 2f
-1:     fnclex
-       xor %eax,%eax
+       and %ecx,%edx
+       push %edx
+       ldmxcsr (%esp)
+       pop %edx
+1:     xor %eax,%eax
        ret
-2:     fnstsw %ax
-       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)
@@ -23,6 +51,7 @@ feclearexcept:
 .type feraiseexcept,@function
 feraiseexcept: 
        mov 4(%esp),%eax
+       and $0x3f,%eax
        sub $32,%esp
        fnstenv (%esp)
        or %al,4(%esp)
@@ -31,9 +60,10 @@ feraiseexcept:
        xor %eax,%eax
        ret
 
-.global fesetround
-.type fesetround,@function
-fesetround:
+.global __fesetround
+.hidden __fesetround
+.type __fesetround,@function
+__fesetround:
        mov 4(%esp),%ecx
        push %eax
        xor %eax,%eax
@@ -41,7 +71,18 @@ fesetround:
        andb $0xf3,1(%esp)
        or %ch,1(%esp)
        fldcw (%esp)
-       pop %ecx
+               # consider sse fenv as well if the cpu has XMM capability
+       call 1f
+1:     addl $__hwcap-1b,(%esp)
+       pop %edx
+       testl $0x02000000,(%edx)
+       jz 1f
+       stmxcsr (%esp)
+       shl $3,%ch
+       andb $0x9f,1(%esp)
+       or %ch,1(%esp)
+       ldmxcsr (%esp)
+1:     pop %ecx
        ret
 
 .global fegetround
@@ -59,32 +100,65 @@ fegetenv:
        mov 4(%esp),%ecx
        xor %eax,%eax
        fnstenv (%ecx)
-       ret
+               # consider sse fenv as well if the cpu has XMM capability
+       call 1f
+1:     addl $__hwcap-1b,(%esp)
+       pop %edx
+       testl $0x02000000,(%edx)
+       jz 1f
+       push %eax
+       stmxcsr (%esp)
+       pop %edx
+       and $0x3f,%edx
+       or %edx,4(%ecx)
+1:     ret
 
 .global fesetenv
 .type fesetenv,@function
 fesetenv:
        mov 4(%esp),%ecx
        xor %eax,%eax
-       test %ecx,%ecx
+       inc %ecx
        jz 1f
-       fldenv (%ecx)
-       ret
+       fldenv -1(%ecx)
+       movl -1(%ecx),%ecx
+       jmp 2f
 1:     push %eax
        push %eax
        push %eax
        push %eax
-       push %eax
+       pushl $0xffff
        push %eax
        pushl $0x37f
        fldenv (%esp)
        add $28,%esp
-       ret
+               # consider sse fenv as well if the cpu has XMM capability
+2:     call 1f
+1:     addl $__hwcap-1b,(%esp)
+       pop %edx
+       testl $0x02000000,(%edx)
+       jz 1f
+               # mxcsr := same rounding mode, cleared exceptions, default mask
+       and $0xc00,%ecx
+       shl $3,%ecx
+       or $0x1f80,%ecx
+       mov %ecx,4(%esp)
+       ldmxcsr 4(%esp)
+1:     ret
 
 .global fetestexcept
 .type fetestexcept,@function
 fetestexcept:
        mov 4(%esp),%ecx
+       and $0x3f,%ecx
        fnstsw %ax
-       and %ecx,%eax
+               # consider sse fenv as well if the cpu has XMM capability
+       call 1f
+1:     addl $__hwcap-1b,(%esp)
+       pop %edx
+       testl $0x02000000,(%edx)
+       jz 1f
+       stmxcsr 4(%esp)
+       or 4(%esp),%eax
+1:     and %ecx,%eax
        ret