fix fenv exception functions to mask their argument
authorSzabolcs Nagy <nsz@port70.net>
Sun, 18 Aug 2013 20:08:18 +0000 (20:08 +0000)
committerSzabolcs Nagy <nsz@port70.net>
Sun, 18 Aug 2013 20:08:18 +0000 (20:08 +0000)
fesetround.c is a wrapper to do the arch independent argument
check (on archs where rounding mode is not stored in 2 bits
__fesetround still has to check its arguments)

on powerpc fe*except functions do not accept the extra invalid
flags of its fpscr register

the useless FENV_ACCESS pragma was removed from feupdateenv

src/fenv/armhf/fenv.s
src/fenv/fenv.c
src/fenv/fesetround.c [new file with mode: 0644]
src/fenv/feupdateenv.c
src/fenv/i386/fenv.s
src/fenv/mips/fenv.s
src/fenv/powerpc/fenv.s
src/fenv/x86_64/fenv.s

index ee81b3d58839a6576859fef336bb902c458b3d27..26ac87e10042c8526e8cacc688a3d23a8d486e30 100644 (file)
@@ -5,9 +5,9 @@ fegetround:
        and r0, r0, #0xc00000
        bx lr
 
-.global fesetround
-.type fesetround,%function
-fesetround:
+.global __fesetround
+.type __fesetround,%function
+__fesetround:
        mrc p10, 7, r3, cr1, cr0, 0
        bic r3, r3, #0xc00000
        orr r3, r3, r0
@@ -18,6 +18,7 @@ fesetround:
 .global fetestexcept
 .type fetestexcept,%function
 fetestexcept:
+       and r0, r0, #0x1f
        mrc p10, 7, r3, cr1, cr0, 0
        and r0, r0, r3
        bx lr
@@ -25,6 +26,7 @@ fetestexcept:
 .global feclearexcept
 .type feclearexcept,%function
 feclearexcept:
+       and r0, r0, #0x1f
        mrc p10, 7, r3, cr1, cr0, 0
        bic r3, r3, r0
        mcr p10, 7, r3, cr1, cr0, 0
@@ -34,6 +36,7 @@ feclearexcept:
 .global feraiseexcept
 .type feraiseexcept,%function
 feraiseexcept:
+       and r0, r0, #0x1f
        mrc p10, 7, r3, cr1, cr0, 0
        orr r3, r3, r0
        mcr p10, 7, r3, cr1, cr0, 0
index b2dfd254b54ebd14121b2fc24201e9ea0d404ef0..5588dad95f428908d7d805dc8b6e1df22970374e 100644 (file)
@@ -22,7 +22,7 @@ int fegetround(void)
        return FE_TONEAREST;
 }
 
-int fesetround(int r)
+int __fesetround(int r)
 {
        return 0;
 }
diff --git a/src/fenv/fesetround.c b/src/fenv/fesetround.c
new file mode 100644 (file)
index 0000000..9bbd4ad
--- /dev/null
@@ -0,0 +1,23 @@
+#include <fenv.h>
+
+/* __fesetround wrapper for arch independent argument check */
+
+int __fesetround(int);
+
+int fesetround(int r)
+{
+       if (r & ~(
+               FE_TONEAREST
+#ifdef FE_DOWNWARD
+               |FE_DOWNWARD
+#endif
+#ifdef FE_UPWARD
+               |FE_UPWARD
+#endif
+#ifdef FE_TOWARDZERO
+               |FE_TOWARDZERO
+#endif
+               ))
+               return -1;
+       return __fesetround(r);
+}
index f45ed7c0141fa21b4e7504d939021507204d9f7e..50cef8e5ca9bef27801c7993aa08c634489aa80b 100644 (file)
@@ -2,7 +2,6 @@
 
 int feupdateenv(const fenv_t *envp)
 {
-       #pragma STDC FENV_ACCESS ON
        int ex = fetestexcept(FE_ALL_EXCEPT);
        fesetenv(envp);
        feraiseexcept(ex);
index a8540add424a3dcb30bd6e971919af6d3efac76a..eaeb6bed01de85c2baab1d9df61a328a61521296 100644 (file)
@@ -4,6 +4,7 @@
 .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
@@ -50,6 +51,7 @@ feclearexcept:
 .type feraiseexcept,@function
 feraiseexcept: 
        mov 4(%esp),%eax
+       and $0x3f,%eax
        sub $32,%esp
        fnstenv (%esp)
        or %al,4(%esp)
@@ -58,9 +60,9 @@ feraiseexcept:
        xor %eax,%eax
        ret
 
-.global fesetround
-.type fesetround,@function
-fesetround:
+.global __fesetround
+.type __fesetround,@function
+__fesetround:
        mov 4(%esp),%ecx
        push %eax
        xor %eax,%eax
@@ -147,6 +149,7 @@ fesetenv:
 .type fetestexcept,@function
 fetestexcept:
        mov 4(%esp),%ecx
+       and $0x3f,%ecx
        fnstsw %ax
                # consider sse fenv as well if the cpu has XMM capability
        call 1f
index 49ff36c061bdc4426570b0ada90a54e5c0c52934..095cb6068f9e2f1fd2f694dc4f7747f04c66b934 100644 (file)
@@ -3,6 +3,7 @@
 .global feclearexcept
 .type  feclearexcept,@function
 feclearexcept:
+       and     $4, $4, 0x7c
        cfc1    $5, $31
        or      $5, $5, $4
        xor     $5, $5, $4
@@ -13,6 +14,7 @@ feclearexcept:
 .global feraiseexcept
 .type  feraiseexcept,@function
 feraiseexcept:
+       and     $4, $4, 0x7c
        cfc1    $5, $31
        or      $5, $5, $4
        ctc1    $5, $31
@@ -22,6 +24,7 @@ feraiseexcept:
 .global fetestexcept
 .type  fetestexcept,@function
 fetestexcept:
+       and     $4, $4, 0x7c
        cfc1    $2, $31
        jr      $ra
        and     $2, $2, $4
@@ -33,9 +36,9 @@ fegetround:
        jr      $ra
        andi    $2, $2, 3
 
-.global fesetround
-.type  fesetround,@function
-fesetround:
+.global __fesetround
+.type __fesetround,@function
+__fesetround:
        cfc1    $5, $31
        li      $6, -4
        and     $5, $5, $6
index 9c424d8e31d9d7d8f83ea4f738b34dbb17c98ab2..3886d168f1ed916b71d2c0757d899b87519ce192 100644 (file)
@@ -1,6 +1,7 @@
 .global feclearexcept
 .type feclearexcept,@function
 feclearexcept:
+       andis 3,3,0x3e00
        # if (r3 & FE_INVALID) r3 |= all_invalid_flags
        andis. 0,3,0x2000
        stwu 1,-16(1)
@@ -28,6 +29,7 @@ feclearexcept:
 .global feraiseexcept
 .type feraiseexcept,@function
 feraiseexcept:
+       andis 3,3,0x3e00
        # if (r3 & FE_INVALID) r3 |= software_invalid_flag
        andis. 0,3,0x2000
        stwu 1,-16(1)
@@ -51,6 +53,7 @@ feraiseexcept:
 .global fetestexcept
 .type fetestexcept,@function
 fetestexcept:
+       andis 3,3,0x3e00
        # return r3 & fpscr
        stwu 1,-16(1)
        mffs 0
@@ -72,9 +75,9 @@ fegetround:
        clrlwi 3,3,30
        blr
 
-.global fesetround
-.type fesetround,@function
-fesetround:
+.global __fesetround
+.type __fesetround,@function
+__fesetround:
        # note: invalid input is not checked, r3 < 4 must hold
        # fpscr = (fpscr & -4U) | r3
        stwu 1,-16(1)
index dda6b61a0b0bf61d9fce5bfeb3d605616c4d6bf4..6aaf25eb1efdf7c355d0d2200b096783ffe3e34d 100644 (file)
@@ -3,6 +3,7 @@
 feclearexcept:
                # maintain exceptions in the sse mxcsr, clear x87 exceptions
        mov %edi,%ecx
+       and $0x3f,%ecx
        fnstsw %ax
        test %eax,%ecx
        jz 1f
@@ -20,16 +21,17 @@ feclearexcept:
 
 .global feraiseexcept
 .type feraiseexcept,@function
-feraiseexcept: 
+feraiseexcept:
+       and $0x3f,%edi
        stmxcsr -8(%rsp)
        or %edi,-8(%rsp)
        ldmxcsr -8(%rsp)
        xor %eax,%eax
        ret
 
-.global fesetround
-.type fesetround,@function
-fesetround:
+.global __fesetround
+.type __fesetround,@function
+__fesetround:
        push %rax
        xor %eax,%eax
        mov %edi,%ecx
@@ -85,6 +87,7 @@ fesetenv:
 .global fetestexcept
 .type fetestexcept,@function
 fetestexcept:
+       and $0x3f,%edi
        push %rax
        stmxcsr (%rsp)
        pop %rsi