ARM: Improve fenv implementation

This commit is contained in:
Wilco 2014-05-15 15:18:40 +01:00 committed by Marcus Shawcroft
parent cf26a0cb6a
commit 1a2f40e5d1
17 changed files with 190 additions and 233 deletions

View File

@ -895,6 +895,25 @@
* nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h * nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h
(pthread_mutex_t): Add lock elision support for s390. (pthread_mutex_t): Add lock elision support for s390.
2014-05-14 Wilco <wdijkstr@arm.com>
* sysdeps/arm/fclrexcpt.c: Cleanup.
* sysdeps/arm/fedisblxcpt.c: Cleanup.
* sysdeps/arm/feenablxcpt.c: Cleanup.
* sysdeps/arm/fegetenv.c: Cleanup.
* sysdeps/arm/fegetexcept.c: Cleanup.
* sysdeps/arm/fegetround.c: Cleanup.
* sysdeps/arm/feholdexcpt.c: Cleanup.
* sysdeps/arm/fesetenv.c: Cleanup.
* sysdeps/arm/fesetround.c: Cleanup.
* sysdeps/arm/feupdateenv.c: Cleanup.
* sysdeps/arm/fgetexcptflg.c: Cleanup.
* sysdeps/arm/fraiseexcpt.c: Cleanup.
* sysdeps/arm/fsetexcptflg.c: Cleanup.
* sysdeps/arm/ftestexcept.c: Cleanup.
* sysdeps/arm/get-rounding-mode.h: Cleanup.
* sysdeps/arm/setfpucw.c: Cleanup.
2014-05-09 Will Newton <will.newton@linaro.org> 2014-05-09 Will Newton <will.newton@linaro.org>
* sysdeps/arm/armv7/strcmp.S: New file. * sysdeps/arm/armv7/strcmp.S: New file.

View File

@ -24,27 +24,20 @@
int int
feclearexcept (int excepts) feclearexcept (int excepts)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned long int temp;
/* Mask out unsupported bits/exceptions. */ /* Fail if a VFP unit isn't present unless nothing needs to be done. */
if (!ARM_HAVE_VFP)
return (excepts != 0);
_FPU_GETCW (fpscr);
excepts &= FE_ALL_EXCEPT; excepts &= FE_ALL_EXCEPT;
/* Get the current floating point status. */
_FPU_GETCW (temp);
/* Clear the relevant bits. */ /* Clear the relevant bits. */
temp = (temp & ~FE_ALL_EXCEPT) | (temp & FE_ALL_EXCEPT & ~excepts); fpscr = (fpscr & ~FE_ALL_EXCEPT) | (fpscr & FE_ALL_EXCEPT & ~excepts);
/* Put the new data in effect. */ _FPU_SETCW (fpscr);
_FPU_SETCW (temp);
/* Success. */
return 0; return 0;
}
/* Unsupported, so fail unless nothing needs to be done. */
return (excepts != 0);
} }
libm_hidden_def (feclearexcept) libm_hidden_def (feclearexcept)

View File

@ -25,23 +25,17 @@
int int
fedisableexcept (int excepts) fedisableexcept (int excepts)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr, new_fpscr;
{
unsigned long int new_exc, old_exc;
_FPU_GETCW(new_exc); /* Fail if a VFP unit isn't present. */
if (!ARM_HAVE_VFP)
old_exc = (new_exc >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
excepts &= FE_ALL_EXCEPT;
new_exc &= ~(excepts << FE_EXCEPT_SHIFT);
_FPU_SETCW(new_exc);
return old_exc;
}
/* Unsupported, so return -1 for failure. */
return -1; return -1;
_FPU_GETCW (fpscr);
excepts &= FE_ALL_EXCEPT;
new_fpscr = fpscr & ~(excepts << FE_EXCEPT_SHIFT);
_FPU_SETCW (new_fpscr);
return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
} }

View File

@ -25,35 +25,27 @@
int int
feenableexcept (int excepts) feenableexcept (int excepts)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr, new_fpscr;
{
unsigned long int new_exc, old_exc;
_FPU_GETCW(new_exc); /* Fail if a VFP unit isn't present. */
if (!ARM_HAVE_VFP)
old_exc = (new_exc >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT; return -1;
_FPU_GETCW (fpscr);
excepts &= FE_ALL_EXCEPT; excepts &= FE_ALL_EXCEPT;
new_fpscr = fpscr | (excepts << FE_EXCEPT_SHIFT);
new_exc |= (excepts << FE_EXCEPT_SHIFT); _FPU_SETCW (new_fpscr);
_FPU_SETCW(new_exc);
if (excepts != 0) if (excepts != 0)
{ {
/* VFPv3 and VFPv4 do not support trapping exceptions, so /* Not all VFP architectures support trapping exceptions, so
test whether the relevant bits were set and fail if test whether the relevant bits were set and fail if not. */
not. */ _FPU_GETCW (new_fpscr);
unsigned int temp; if ((new_fpscr & (excepts << FE_EXCEPT_SHIFT))
_FPU_GETCW (temp);
if ((temp & (excepts << FE_EXCEPT_SHIFT))
!= (excepts << FE_EXCEPT_SHIFT)) != (excepts << FE_EXCEPT_SHIFT))
return -1; return -1;
} }
return old_exc; return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
}
/* Unsupported, so return -1 for failure. */
return -1;
} }

View File

@ -24,17 +24,14 @@
int int
fegetenv (fenv_t *envp) fegetenv (fenv_t *envp)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned long int temp;
_FPU_GETCW (temp);
envp->__cw = temp;
/* Success. */ /* Fail if a VFP unit isn't present. */
return 0; if (!ARM_HAVE_VFP)
}
/* Unsupported, so fail. */
return 1; return 1;
_FPU_GETCW (fpscr);
envp->__cw = fpscr;
return 0;
} }
libm_hidden_def (fegetenv) libm_hidden_def (fegetenv)

View File

@ -25,15 +25,13 @@
int int
fegetexcept (void) fegetexcept (void)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned long temp;
_FPU_GETCW (temp); /* Return with all exceptions disabled if a VFP unit isn't present. */
if (!ARM_HAVE_VFP)
return (temp >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
}
/* Unsupported. Return all exceptions disabled. */
return 0; return 0;
_FPU_GETCW (fpscr);
return (fpscr >> FE_EXCEPT_SHIFT) & FE_ALL_EXCEPT;
} }

View File

@ -24,17 +24,14 @@
int int
fegetround (void) fegetround (void)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned int temp;
/* Get the current environment. */ /* FE_TONEAREST is the only supported rounding mode
_FPU_GETCW (temp); if a VFP unit isn't present. */
if (!ARM_HAVE_VFP)
return temp & FE_TOWARDZERO;
}
/* The current soft-float implementation only handles TONEAREST. */
return FE_TONEAREST; return FE_TONEAREST;
_FPU_GETCW (fpscr);
return fpscr & FE_TOWARDZERO;
} }
libm_hidden_def (fegetround) libm_hidden_def (fegetround)

View File

@ -24,27 +24,23 @@
int int
feholdexcept (fenv_t *envp) feholdexcept (fenv_t *envp)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned long int temp;
/* Store the environment. */ /* Fail if a VFP unit isn't present. */
_FPU_GETCW(temp); if (!ARM_HAVE_VFP)
envp->__cw = temp; return 1;
_FPU_GETCW (fpscr);
envp->__cw = fpscr;
/* Now set all exceptions to non-stop. */ /* Now set all exceptions to non-stop. */
temp &= ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT); fpscr &= ~(FE_ALL_EXCEPT << FE_EXCEPT_SHIFT);
/* And clear all exception flags. */ /* And clear all exception flags. */
temp &= ~FE_ALL_EXCEPT; fpscr &= ~FE_ALL_EXCEPT;
_FPU_SETCW(temp);
_FPU_SETCW (fpscr);
return 0; return 0;
}
/* Unsupported, so fail. */
return 1;
} }
libm_hidden_def (feholdexcept) libm_hidden_def (feholdexcept)

View File

@ -24,38 +24,36 @@
int int
fesetenv (const fenv_t *envp) fesetenv (const fenv_t *envp)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned int temp;
_FPU_GETCW (temp); /* Fail if a VFP unit isn't present. */
temp &= _FPU_RESERVED; if (!ARM_HAVE_VFP)
return 1;
_FPU_GETCW (fpscr);
/* Preserve the reserved FPSCR flags. */
fpscr &= _FPU_RESERVED;
if (envp == FE_DFL_ENV) if (envp == FE_DFL_ENV)
temp |= _FPU_DEFAULT; fpscr |= _FPU_DEFAULT;
else if (envp == FE_NOMASK_ENV) else if (envp == FE_NOMASK_ENV)
temp |= _FPU_IEEE; fpscr |= _FPU_IEEE;
else else
temp |= envp->__cw & ~_FPU_RESERVED; fpscr |= envp->__cw & ~_FPU_RESERVED;
_FPU_SETCW (temp); _FPU_SETCW (fpscr);
if (envp == FE_NOMASK_ENV) if (envp == FE_NOMASK_ENV)
{ {
/* VFPv3 and VFPv4 do not support trapping exceptions, so /* Not all VFP architectures support trapping exceptions, so
test whether the relevant bits were set and fail if test whether the relevant bits were set and fail if not. */
not. */ _FPU_GETCW (fpscr);
_FPU_GETCW (temp); if ((fpscr & _FPU_IEEE) != _FPU_IEEE)
if ((temp & _FPU_IEEE) != _FPU_IEEE)
return 1; return 1;
} }
/* Success. */
return 0; return 0;
}
/* Unsupported, so fail. */
return 1;
} }
libm_hidden_def (fesetenv) libm_hidden_def (fesetenv)

View File

@ -24,30 +24,21 @@
int int
fesetround (int round) fesetround (int round)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
fpu_control_t temp;
switch (round) /* FE_TONEAREST is the only supported rounding mode
{ if a VFP unit isn't present. */
case FE_TONEAREST: if (!ARM_HAVE_VFP)
case FE_UPWARD: return (round == FE_TONEAREST) ? 0 : 1;
case FE_DOWNWARD:
case FE_TOWARDZERO:
_FPU_GETCW (temp);
temp = (temp & ~FE_TOWARDZERO) | round;
_FPU_SETCW (temp);
return 0;
default:
return 1;
}
}
else if (round == FE_TONEAREST)
/* This is the only supported rounding mode for soft-fp. */
return 0;
/* Unsupported, so fail. */ /* Fail if the rounding mode is not valid. */
if (round & ~FE_TOWARDZERO)
return 1; return 1;
_FPU_GETCW (fpscr);
fpscr = (fpscr & ~FE_TOWARDZERO) | round;
_FPU_SETCW (fpscr);
return 0;
} }
libm_hidden_def (fesetround) libm_hidden_def (fesetround)

View File

@ -25,24 +25,19 @@
int int
feupdateenv (const fenv_t *envp) feupdateenv (const fenv_t *envp)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned int temp;
/* Get the current exception state. */ /* Fail if a VFP unit isn't present. */
_FPU_GETCW (temp); if (!ARM_HAVE_VFP)
return 1;
_FPU_GETCW (fpscr);
/* Install new environment. */ /* Install new environment. */
fesetenv (envp); fesetenv (envp);
/* Raise the saved exceptions. */ /* Raise the saved exceptions. */
feraiseexcept (temp & FE_ALL_EXCEPT); feraiseexcept (fpscr & FE_ALL_EXCEPT);
/* Success. */
return 0; return 0;
}
/* Unsupported, so fail. */
return 1;
} }
libm_hidden_def (feupdateenv) libm_hidden_def (feupdateenv)

View File

@ -25,19 +25,14 @@
int int
fegetexceptflag (fexcept_t *flagp, int excepts) fegetexceptflag (fexcept_t *flagp, int excepts)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
unsigned long temp;
/* Get the current exceptions. */ /* Fail if a VFP unit isn't present. */
_FPU_GETCW (temp); if (!ARM_HAVE_VFP)
*flagp = temp & excepts & FE_ALL_EXCEPT;
/* Success. */
return 0;
}
/* Unsupported, so fail. */
return 1; return 1;
_FPU_GETCW (fpscr);
*flagp = fpscr & excepts & FE_ALL_EXCEPT;
return 0;
} }

View File

@ -25,9 +25,12 @@
int int
feraiseexcept (int excepts) feraiseexcept (int excepts)
{ {
if (ARM_HAVE_VFP) /* Fail if a VFP unit isn't present unless nothing needs to be done. */
if (!ARM_HAVE_VFP)
return (excepts != 0);
else
{ {
int fpscr; fpu_control_t fpscr;
const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX, const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX,
fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0, fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0,
fp_three = 3.0; fp_three = 3.0;
@ -98,9 +101,6 @@ feraiseexcept (int excepts)
/* Success. */ /* Success. */
return 0; return 0;
} }
/* Unsupported, so fail unless nothing needs to be done. */
return (excepts != 0);
} }
libm_hidden_def (feraiseexcept) libm_hidden_def (feraiseexcept)

View File

@ -25,24 +25,19 @@
int int
fesetexceptflag (const fexcept_t *flagp, int excepts) fesetexceptflag (const fexcept_t *flagp, int excepts)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
fexcept_t temp;
/* Get the current environment. */ /* Fail if a VFP unit isn't present unless nothing needs to be done. */
_FPU_GETCW (temp); if (!ARM_HAVE_VFP)
return (excepts != 0);
_FPU_GETCW (fpscr);
/* Set the desired exception mask. */ /* Set the desired exception mask. */
temp &= ~(excepts & FE_ALL_EXCEPT); fpscr &= ~(excepts & FE_ALL_EXCEPT);
temp |= (*flagp & excepts & FE_ALL_EXCEPT); fpscr |= (*flagp & excepts & FE_ALL_EXCEPT);
/* Save state back to the FPU. */ /* Save state back to the FPU. */
_FPU_SETCW (temp); _FPU_SETCW (fpscr);
/* Success. */
return 0; return 0;
}
/* Unsupported, so fail unless nothing needs to be done. */
return (excepts != 0);
} }

View File

@ -24,17 +24,15 @@
int int
fetestexcept (int excepts) fetestexcept (int excepts)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
fexcept_t temp; /* Return no exception flags if a VFP unit isn't present. */
if (!ARM_HAVE_VFP)
return 0;
/* Get current exceptions. */ /* Get current exceptions. */
_FPU_GETCW(temp); _FPU_GETCW (fpscr);
return temp & excepts & FE_ALL_EXCEPT; return fpscr & excepts & FE_ALL_EXCEPT;
}
/* Unsupported, return 0. */
return 0;
} }
libm_hidden_def (fetestexcept) libm_hidden_def (fetestexcept)

View File

@ -28,15 +28,15 @@
static inline int static inline int
get_rounding_mode (void) get_rounding_mode (void)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
fpu_control_t fc;
_FPU_GETCW (fc); /* FE_TONEAREST is the only supported rounding mode
return fc & FE_TOWARDZERO; if a VFP unit isn't present. */
} if (!ARM_HAVE_VFP)
else
return FE_TONEAREST; return FE_TONEAREST;
_FPU_GETCW (fpscr);
return fpscr & FE_TOWARDZERO;
} }
#endif /* get-rounding-mode.h */ #endif /* get-rounding-mode.h */

View File

@ -24,20 +24,19 @@
void void
__setfpucw (fpu_control_t set) __setfpucw (fpu_control_t set)
{ {
if (ARM_HAVE_VFP) fpu_control_t fpscr;
{
fpu_control_t cw; /* Do nothing if a VFP unit isn't present. */
if (!ARM_HAVE_VFP)
return;
/* Fetch the current control word. */ /* Fetch the current control word. */
_FPU_GETCW (cw); _FPU_GETCW (fpscr);
/* Preserve the reserved bits, and set the rest as the user /* Preserve the reserved bits, and set the rest as the user
specified (or the default, if the user gave zero). */ specified (or the default, if the user gave zero). */
cw &= _FPU_RESERVED; fpscr &= _FPU_RESERVED;
cw |= set & ~_FPU_RESERVED; fpscr |= set & ~_FPU_RESERVED;
_FPU_SETCW (cw); _FPU_SETCW (fpscr);
}
/* Do nothing if a VFP unit isn't present. */
} }