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
and r0, r0, #0xc00000
bx lr
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
mrc p10, 7, r3, cr1, cr0, 0
bic r3, r3, #0xc00000
orr r3, r3, r0
.global fetestexcept
.type fetestexcept,%function
fetestexcept:
.global fetestexcept
.type fetestexcept,%function
fetestexcept:
mrc p10, 7, r3, cr1, cr0, 0
and r0, r0, r3
bx lr
mrc p10, 7, r3, cr1, cr0, 0
and r0, r0, r3
bx lr
.global feclearexcept
.type feclearexcept,%function
feclearexcept:
.global feclearexcept
.type feclearexcept,%function
feclearexcept:
mrc p10, 7, r3, cr1, cr0, 0
bic r3, r3, r0
mcr p10, 7, r3, cr1, cr0, 0
mrc p10, 7, r3, cr1, cr0, 0
bic r3, r3, r0
mcr p10, 7, r3, cr1, cr0, 0
.global feraiseexcept
.type feraiseexcept,%function
feraiseexcept:
.global feraiseexcept
.type feraiseexcept,%function
feraiseexcept:
mrc p10, 7, r3, cr1, cr0, 0
orr r3, r3, r0
mcr p10, 7, r3, cr1, cr0, 0
mrc p10, 7, r3, cr1, cr0, 0
orr r3, r3, r0
mcr p10, 7, r3, cr1, cr0, 0
--- /dev/null
+#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);
+}
int feupdateenv(const fenv_t *envp)
{
int feupdateenv(const fenv_t *envp)
{
- #pragma STDC FENV_ACCESS ON
int ex = fetestexcept(FE_ALL_EXCEPT);
fesetenv(envp);
feraiseexcept(ex);
int ex = fetestexcept(FE_ALL_EXCEPT);
fesetenv(envp);
feraiseexcept(ex);
.type feclearexcept,@function
feclearexcept:
mov 4(%esp),%ecx
.type feclearexcept,@function
feclearexcept:
mov 4(%esp),%ecx
fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability
call 1f
fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability
call 1f
.type feraiseexcept,@function
feraiseexcept:
mov 4(%esp),%eax
.type feraiseexcept,@function
feraiseexcept:
mov 4(%esp),%eax
sub $32,%esp
fnstenv (%esp)
or %al,4(%esp)
sub $32,%esp
fnstenv (%esp)
or %al,4(%esp)
-.global fesetround
-.type fesetround,@function
-fesetround:
+.global __fesetround
+.type __fesetround,@function
+__fesetround:
mov 4(%esp),%ecx
push %eax
xor %eax,%eax
mov 4(%esp),%ecx
push %eax
xor %eax,%eax
.type fetestexcept,@function
fetestexcept:
mov 4(%esp),%ecx
.type fetestexcept,@function
fetestexcept:
mov 4(%esp),%ecx
fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability
call 1f
fnstsw %ax
# consider sse fenv as well if the cpu has XMM capability
call 1f
.global feclearexcept
.type feclearexcept,@function
feclearexcept:
.global feclearexcept
.type feclearexcept,@function
feclearexcept:
cfc1 $5, $31
or $5, $5, $4
xor $5, $5, $4
cfc1 $5, $31
or $5, $5, $4
xor $5, $5, $4
.global feraiseexcept
.type feraiseexcept,@function
feraiseexcept:
.global feraiseexcept
.type feraiseexcept,@function
feraiseexcept:
cfc1 $5, $31
or $5, $5, $4
ctc1 $5, $31
cfc1 $5, $31
or $5, $5, $4
ctc1 $5, $31
.global fetestexcept
.type fetestexcept,@function
fetestexcept:
.global fetestexcept
.type fetestexcept,@function
fetestexcept:
cfc1 $2, $31
jr $ra
and $2, $2, $4
cfc1 $2, $31
jr $ra
and $2, $2, $4
-.global fesetround
-.type fesetround,@function
-fesetround:
+.global __fesetround
+.type __fesetround,@function
+__fesetround:
cfc1 $5, $31
li $6, -4
and $5, $5, $6
cfc1 $5, $31
li $6, -4
and $5, $5, $6
.global feclearexcept
.type feclearexcept,@function
feclearexcept:
.global feclearexcept
.type feclearexcept,@function
feclearexcept:
# if (r3 & FE_INVALID) r3 |= all_invalid_flags
andis. 0,3,0x2000
stwu 1,-16(1)
# if (r3 & FE_INVALID) r3 |= all_invalid_flags
andis. 0,3,0x2000
stwu 1,-16(1)
.global feraiseexcept
.type feraiseexcept,@function
feraiseexcept:
.global feraiseexcept
.type feraiseexcept,@function
feraiseexcept:
# if (r3 & FE_INVALID) r3 |= software_invalid_flag
andis. 0,3,0x2000
stwu 1,-16(1)
# if (r3 & FE_INVALID) r3 |= software_invalid_flag
andis. 0,3,0x2000
stwu 1,-16(1)
.global fetestexcept
.type fetestexcept,@function
fetestexcept:
.global fetestexcept
.type fetestexcept,@function
fetestexcept:
# return r3 & fpscr
stwu 1,-16(1)
mffs 0
# return r3 & fpscr
stwu 1,-16(1)
mffs 0
-.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)
# note: invalid input is not checked, r3 < 4 must hold
# fpscr = (fpscr & -4U) | r3
stwu 1,-16(1)
feclearexcept:
# maintain exceptions in the sse mxcsr, clear x87 exceptions
mov %edi,%ecx
feclearexcept:
# maintain exceptions in the sse mxcsr, clear x87 exceptions
mov %edi,%ecx
fnstsw %ax
test %eax,%ecx
jz 1f
fnstsw %ax
test %eax,%ecx
jz 1f
.global feraiseexcept
.type feraiseexcept,@function
.global feraiseexcept
.type feraiseexcept,@function
+feraiseexcept:
+ and $0x3f,%edi
stmxcsr -8(%rsp)
or %edi,-8(%rsp)
ldmxcsr -8(%rsp)
xor %eax,%eax
ret
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
push %rax
xor %eax,%eax
mov %edi,%ecx
.global fetestexcept
.type fetestexcept,@function
fetestexcept:
.global fetestexcept
.type fetestexcept,@function
fetestexcept:
push %rax
stmxcsr (%rsp)
pop %rsi
push %rax
stmxcsr (%rsp)
pop %rsi