add sse fenv support on i386 through hwcap
authorSzabolcs Nagy <nsz@port70.net>
Sat, 17 Aug 2013 02:40:44 +0000 (02:40 +0000)
committerSzabolcs Nagy <nsz@port70.net>
Sun, 18 Aug 2013 16:27:20 +0000 (16:27 +0000)
the sse and x87 rounding modes should be always the same,
the visible exception flags are the bitwise or of the two
fenv states (so it's enough to query the rounding mode or
raise exceptions on one fenv)

src/fenv/i386/fenv.s
src/fenv/x86_64/fenv.s

index 471d2af8e2e9f530df98268249a02a1a22edb0e6..9bba40a5e3a01f2ffeb25a7804383b40a6be2b66 100644 (file)
@@ -1,14 +1,26 @@
+.hidden __hwcap
+
 .global feclearexcept
 .type feclearexcept,@function
 feclearexcept: 
        mov 4(%esp),%ecx
        not %ecx
-       test $0x3f,%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 4(%esp)
+       and %ecx,4(%esp)
+       ldmxcsr 4(%esp)
+1:     test $0x3f,%ecx
        jnz 2f
 1:     fnclex
        xor %eax,%eax
        ret
 2:     fnstsw %ax
+               # TODO: only load/store fenv if exceptions arent clear yet
        and %ecx,%eax
        jz 1b
        sub $32,%esp
@@ -41,7 +53,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)
+       jmp 1f
+       stmxcsr (%esp)
+       shl $3,%ch
+       andb $0x9f,1(%esp)
+       or %ch,1(%esp)
+       ldmxcsr (%esp)
+1:     pop %ecx
        ret
 
 .global fegetround
@@ -59,7 +82,18 @@ 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
@@ -69,7 +103,8 @@ fesetenv:
        inc %ecx
        jz 1f
        fldenv -1(%ecx)
-       ret
+       movl -1(%ecx),%ecx
+       jmp 2f
 1:     push %eax
        push %eax
        push %eax
@@ -79,12 +114,32 @@ fesetenv:
        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
        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
index 443e35a27cc513f23b5d367a47a907cc1bfbb0ae..c48dade394c2e001f14ccf35c3b5ed8b9e8bd6d4 100644 (file)
@@ -28,9 +28,6 @@ feraiseexcept:
        stmxcsr -8(%rsp)
        or %edi,-8(%rsp)
        ldmxcsr -8(%rsp)
-       fnstenv -32(%rsp)
-       or %edi,-28(%rsp)
-       fldenv -32(%rsp)
        xor %eax,%eax
        ret