From a6b0170a7f51fdea9beec57ae794221290af232b Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Sun, 18 Aug 2013 20:08:18 +0000 Subject: fix fenv exception functions to mask their argument 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 | 9 ++++++--- src/fenv/fenv.c | 2 +- src/fenv/fesetround.c | 23 +++++++++++++++++++++++ src/fenv/feupdateenv.c | 1 - src/fenv/i386/fenv.s | 9 ++++++--- src/fenv/mips/fenv.s | 9 ++++++--- src/fenv/powerpc/fenv.s | 9 ++++++--- src/fenv/x86_64/fenv.s | 11 +++++++---- 8 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 src/fenv/fesetround.c diff --git a/src/fenv/armhf/fenv.s b/src/fenv/armhf/fenv.s index ee81b3d5..26ac87e1 100644 --- a/src/fenv/armhf/fenv.s +++ b/src/fenv/armhf/fenv.s @@ -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 diff --git a/src/fenv/fenv.c b/src/fenv/fenv.c index b2dfd254..5588dad9 100644 --- a/src/fenv/fenv.c +++ b/src/fenv/fenv.c @@ -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 index 00000000..9bbd4ade --- /dev/null +++ b/src/fenv/fesetround.c @@ -0,0 +1,23 @@ +#include + +/* __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); +} diff --git a/src/fenv/feupdateenv.c b/src/fenv/feupdateenv.c index f45ed7c0..50cef8e5 100644 --- a/src/fenv/feupdateenv.c +++ b/src/fenv/feupdateenv.c @@ -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); diff --git a/src/fenv/i386/fenv.s b/src/fenv/i386/fenv.s index a8540add..eaeb6bed 100644 --- a/src/fenv/i386/fenv.s +++ b/src/fenv/i386/fenv.s @@ -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 diff --git a/src/fenv/mips/fenv.s b/src/fenv/mips/fenv.s index 49ff36c0..095cb606 100644 --- a/src/fenv/mips/fenv.s +++ b/src/fenv/mips/fenv.s @@ -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 diff --git a/src/fenv/powerpc/fenv.s b/src/fenv/powerpc/fenv.s index 9c424d8e..3886d168 100644 --- a/src/fenv/powerpc/fenv.s +++ b/src/fenv/powerpc/fenv.s @@ -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) diff --git a/src/fenv/x86_64/fenv.s b/src/fenv/x86_64/fenv.s index dda6b61a..6aaf25eb 100644 --- a/src/fenv/x86_64/fenv.s +++ b/src/fenv/x86_64/fenv.s @@ -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 -- cgit v1.2.1