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
This commit is contained in:
Szabolcs Nagy 2013-08-18 20:08:18 +00:00
commit a6b0170a7f
8 changed files with 55 additions and 18 deletions

View file

@ -5,9 +5,9 @@ fegetround:
and r0, r0, #0xc00000 and r0, r0, #0xc00000
bx lr bx lr
.global fesetround .global __fesetround
.type fesetround,%function .type __fesetround,%function
fesetround: __fesetround:
mrc p10, 7, r3, cr1, cr0, 0 mrc p10, 7, r3, cr1, cr0, 0
bic r3, r3, #0xc00000 bic r3, r3, #0xc00000
orr r3, r3, r0 orr r3, r3, r0
@ -18,6 +18,7 @@ fesetround:
.global fetestexcept .global fetestexcept
.type fetestexcept,%function .type fetestexcept,%function
fetestexcept: fetestexcept:
and r0, r0, #0x1f
mrc p10, 7, r3, cr1, cr0, 0 mrc p10, 7, r3, cr1, cr0, 0
and r0, r0, r3 and r0, r0, r3
bx lr bx lr
@ -25,6 +26,7 @@ fetestexcept:
.global feclearexcept .global feclearexcept
.type feclearexcept,%function .type feclearexcept,%function
feclearexcept: feclearexcept:
and r0, r0, #0x1f
mrc p10, 7, r3, cr1, cr0, 0 mrc p10, 7, r3, cr1, cr0, 0
bic r3, r3, r0 bic r3, r3, r0
mcr p10, 7, r3, cr1, cr0, 0 mcr p10, 7, r3, cr1, cr0, 0
@ -34,6 +36,7 @@ feclearexcept:
.global feraiseexcept .global feraiseexcept
.type feraiseexcept,%function .type feraiseexcept,%function
feraiseexcept: feraiseexcept:
and r0, r0, #0x1f
mrc p10, 7, r3, cr1, cr0, 0 mrc p10, 7, r3, cr1, cr0, 0
orr r3, r3, r0 orr r3, r3, r0
mcr p10, 7, r3, cr1, cr0, 0 mcr p10, 7, r3, cr1, cr0, 0

View file

@ -22,7 +22,7 @@ int fegetround(void)
return FE_TONEAREST; return FE_TONEAREST;
} }
int fesetround(int r) int __fesetround(int r)
{ {
return 0; return 0;
} }

23
src/fenv/fesetround.c Normal file
View file

@ -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);
}

View file

@ -2,7 +2,6 @@
int feupdateenv(const fenv_t *envp) int feupdateenv(const fenv_t *envp)
{ {
#pragma STDC FENV_ACCESS ON
int ex = fetestexcept(FE_ALL_EXCEPT); int ex = fetestexcept(FE_ALL_EXCEPT);
fesetenv(envp); fesetenv(envp);
feraiseexcept(ex); feraiseexcept(ex);

View file

@ -4,6 +4,7 @@
.type feclearexcept,@function .type feclearexcept,@function
feclearexcept: feclearexcept:
mov 4(%esp),%ecx mov 4(%esp),%ecx
and $0x3f,%ecx
fnstsw %ax fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability # consider sse fenv as well if the cpu has XMM capability
call 1f call 1f
@ -50,6 +51,7 @@ feclearexcept:
.type feraiseexcept,@function .type feraiseexcept,@function
feraiseexcept: feraiseexcept:
mov 4(%esp),%eax mov 4(%esp),%eax
and $0x3f,%eax
sub $32,%esp sub $32,%esp
fnstenv (%esp) fnstenv (%esp)
or %al,4(%esp) or %al,4(%esp)
@ -58,9 +60,9 @@ feraiseexcept:
xor %eax,%eax xor %eax,%eax
ret ret
.global fesetround .global __fesetround
.type fesetround,@function .type __fesetround,@function
fesetround: __fesetround:
mov 4(%esp),%ecx mov 4(%esp),%ecx
push %eax push %eax
xor %eax,%eax xor %eax,%eax
@ -147,6 +149,7 @@ fesetenv:
.type fetestexcept,@function .type fetestexcept,@function
fetestexcept: fetestexcept:
mov 4(%esp),%ecx mov 4(%esp),%ecx
and $0x3f,%ecx
fnstsw %ax fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability # consider sse fenv as well if the cpu has XMM capability
call 1f call 1f

View file

@ -3,6 +3,7 @@
.global feclearexcept .global feclearexcept
.type feclearexcept,@function .type feclearexcept,@function
feclearexcept: feclearexcept:
and $4, $4, 0x7c
cfc1 $5, $31 cfc1 $5, $31
or $5, $5, $4 or $5, $5, $4
xor $5, $5, $4 xor $5, $5, $4
@ -13,6 +14,7 @@ feclearexcept:
.global feraiseexcept .global feraiseexcept
.type feraiseexcept,@function .type feraiseexcept,@function
feraiseexcept: feraiseexcept:
and $4, $4, 0x7c
cfc1 $5, $31 cfc1 $5, $31
or $5, $5, $4 or $5, $5, $4
ctc1 $5, $31 ctc1 $5, $31
@ -22,6 +24,7 @@ feraiseexcept:
.global fetestexcept .global fetestexcept
.type fetestexcept,@function .type fetestexcept,@function
fetestexcept: fetestexcept:
and $4, $4, 0x7c
cfc1 $2, $31 cfc1 $2, $31
jr $ra jr $ra
and $2, $2, $4 and $2, $2, $4
@ -33,9 +36,9 @@ fegetround:
jr $ra jr $ra
andi $2, $2, 3 andi $2, $2, 3
.global fesetround .global __fesetround
.type fesetround,@function .type __fesetround,@function
fesetround: __fesetround:
cfc1 $5, $31 cfc1 $5, $31
li $6, -4 li $6, -4
and $5, $5, $6 and $5, $5, $6

View file

@ -1,6 +1,7 @@
.global feclearexcept .global feclearexcept
.type feclearexcept,@function .type feclearexcept,@function
feclearexcept: feclearexcept:
andis 3,3,0x3e00
# if (r3 & FE_INVALID) r3 |= all_invalid_flags # if (r3 & FE_INVALID) r3 |= all_invalid_flags
andis. 0,3,0x2000 andis. 0,3,0x2000
stwu 1,-16(1) stwu 1,-16(1)
@ -28,6 +29,7 @@ feclearexcept:
.global feraiseexcept .global feraiseexcept
.type feraiseexcept,@function .type feraiseexcept,@function
feraiseexcept: feraiseexcept:
andis 3,3,0x3e00
# if (r3 & FE_INVALID) r3 |= software_invalid_flag # if (r3 & FE_INVALID) r3 |= software_invalid_flag
andis. 0,3,0x2000 andis. 0,3,0x2000
stwu 1,-16(1) stwu 1,-16(1)
@ -51,6 +53,7 @@ feraiseexcept:
.global fetestexcept .global fetestexcept
.type fetestexcept,@function .type fetestexcept,@function
fetestexcept: fetestexcept:
andis 3,3,0x3e00
# return r3 & fpscr # return r3 & fpscr
stwu 1,-16(1) stwu 1,-16(1)
mffs 0 mffs 0
@ -72,9 +75,9 @@ fegetround:
clrlwi 3,3,30 clrlwi 3,3,30
blr blr
.global fesetround .global __fesetround
.type fesetround,@function .type __fesetround,@function
fesetround: __fesetround:
# note: invalid input is not checked, r3 < 4 must hold # note: invalid input is not checked, r3 < 4 must hold
# fpscr = (fpscr & -4U) | r3 # fpscr = (fpscr & -4U) | r3
stwu 1,-16(1) stwu 1,-16(1)

View file

@ -3,6 +3,7 @@
feclearexcept: feclearexcept:
# maintain exceptions in the sse mxcsr, clear x87 exceptions # maintain exceptions in the sse mxcsr, clear x87 exceptions
mov %edi,%ecx mov %edi,%ecx
and $0x3f,%ecx
fnstsw %ax fnstsw %ax
test %eax,%ecx test %eax,%ecx
jz 1f jz 1f
@ -20,16 +21,17 @@ feclearexcept:
.global feraiseexcept .global feraiseexcept
.type feraiseexcept,@function .type feraiseexcept,@function
feraiseexcept: feraiseexcept:
and $0x3f,%edi
stmxcsr -8(%rsp) stmxcsr -8(%rsp)
or %edi,-8(%rsp) or %edi,-8(%rsp)
ldmxcsr -8(%rsp) ldmxcsr -8(%rsp)
xor %eax,%eax xor %eax,%eax
ret ret
.global fesetround .global __fesetround
.type fesetround,@function .type __fesetround,@function
fesetround: __fesetround:
push %rax push %rax
xor %eax,%eax xor %eax,%eax
mov %edi,%ecx mov %edi,%ecx
@ -85,6 +87,7 @@ fesetenv:
.global fetestexcept .global fetestexcept
.type fetestexcept,@function .type fetestexcept,@function
fetestexcept: fetestexcept:
and $0x3f,%edi
push %rax push %rax
stmxcsr (%rsp) stmxcsr (%rsp)
pop %rsi pop %rsi