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:
parent
d8764bf840
commit
a6b0170a7f
8 changed files with 55 additions and 18 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
23
src/fenv/fesetround.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue