about summary refs log tree commit diff
path: root/src/fenv
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2013-08-18 20:08:18 +0000
committerSzabolcs Nagy <nsz@port70.net>2013-08-18 20:08:18 +0000
commita6b0170a7f51fdea9beec57ae794221290af232b (patch)
tree22651ba3480fc272933133af780e6beb10ab2d3d /src/fenv
parentd8764bf84022397ff9d22310f78fcd78d801e2bf (diff)
downloadmusl-a6b0170a7f51fdea9beec57ae794221290af232b.tar.gz
musl-a6b0170a7f51fdea9beec57ae794221290af232b.tar.xz
musl-a6b0170a7f51fdea9beec57ae794221290af232b.zip
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
Diffstat (limited to 'src/fenv')
-rw-r--r--src/fenv/armhf/fenv.s9
-rw-r--r--src/fenv/fenv.c2
-rw-r--r--src/fenv/fesetround.c23
-rw-r--r--src/fenv/feupdateenv.c1
-rw-r--r--src/fenv/i386/fenv.s9
-rw-r--r--src/fenv/mips/fenv.s9
-rw-r--r--src/fenv/powerpc/fenv.s9
-rw-r--r--src/fenv/x86_64/fenv.s11
8 files changed, 55 insertions, 18 deletions
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 <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);
+}
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