libroot: Flesh out glibc floating point support for ARM.
The last time someone touched this directory, there was no floating point support configured in ARM. Now we are targeting ARMv7a+, which always has a hard FPU, so we need this now. With this, a haiku.hpkg can (finally) be built again (at least under lld, anyway!)
This commit is contained in:
@@ -3,15 +3,16 @@ SubDir HAIKU_TOP src system libroot posix glibc arch arm ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch $(TARGET_ARCH) ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch generic ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc stdlib ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc math ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ;
|
||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src system libroot posix glibc arch generic ;
|
||||
|
||||
UsePrivateHeaders libroot ;
|
||||
|
||||
|
||||
if $(OPTIM) = -O0 {
|
||||
OPTIM = -O ;
|
||||
}
|
||||
@@ -21,67 +22,116 @@ DEBUG = 0 ;
|
||||
|
||||
SubDirCcFlags -D_GNU_SOURCE -D_IEEE_LIBM ;
|
||||
|
||||
# Note: There is no *l() support yet. Our compiler says sizeof(long double) = 8,
|
||||
# while there are only 96 and 128 bit implementation in glibc.
|
||||
local genericSources =
|
||||
lshift.c rshift.c submul_1.c
|
||||
s_finite.c s_finitef.c
|
||||
add_n.c sub_n.c
|
||||
addmul_1.c mul_1.c
|
||||
|
||||
cmp.c dbl2mpn.c divrem.c
|
||||
mpn2dbl.c mpn2flt.c mpn2ldbl.c
|
||||
mul.c mul_n.c
|
||||
s_isinf.c s_isinff.c
|
||||
s_isnan.c s_isnanf.c
|
||||
s_signbit.c s_signbitf.c
|
||||
|
||||
s_nan.c s_nanf.c
|
||||
e_hypot.c e_hypotf.c
|
||||
w_hypot.c w_hypotf.c
|
||||
s_fpclassify.c s_fpclassifyf.c
|
||||
s_clog.c s_clogf.c
|
||||
s_log1p.c s_log1pf.c
|
||||
s_csqrt.c s_csqrtf.c
|
||||
s_floor.c s_floorf.c
|
||||
s_ceil.c s_ceilf.c
|
||||
s_modf.c
|
||||
w_powf.c e_powf.c
|
||||
w_pow.c e_pow.c slowpow.c
|
||||
w_exp.c e_exp.c slowexp.c
|
||||
s_frexp.c s_expm1.c
|
||||
dosincos.c
|
||||
doasin.c
|
||||
sincos32.c
|
||||
branred.c
|
||||
cmp.c dbl2mpn.c divrem.c
|
||||
doasin.c dosincos.c
|
||||
halfulp.c
|
||||
mpa.c mplog.c mpexp.c
|
||||
s_sin.c
|
||||
s_atan.c s_atanf.c
|
||||
s_tan.c
|
||||
e_asin.c e_asinl.c
|
||||
w_asin.c
|
||||
e_log10.c w_log10.c
|
||||
e_logf.c e_logl.c
|
||||
e_acos.c w_acos.c
|
||||
e_atan2.c
|
||||
w_atan2.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c
|
||||
e_sqrtl.c
|
||||
e_fmod.c w_fmod.c
|
||||
e_log.c w_log.c
|
||||
e_cosh.c w_cosh.c
|
||||
e_sinh.c w_sinh.c
|
||||
s_cosf.c k_cosf.c
|
||||
s_sinf.c k_sinf.c
|
||||
s_ldexp.c s_ldexpf.c
|
||||
s_scalbnf.c s_scalbn.c
|
||||
s_copysign.c s_copysignf.c
|
||||
s_tanh.c s_tanf.c k_tanf.c
|
||||
s_lround.c s_lroundf.c s_round.c s_roundf.c
|
||||
s_rint.c s_rintf.c s_lrintf.c
|
||||
e_fmodf.c w_fmodf.c
|
||||
e_atan2f.c w_atan2f.c
|
||||
e_rem_pio2f.c k_rem_pio2f.c
|
||||
|
||||
memrchr.c
|
||||
mpa.c mpatan.c mpatan2.c mpexp.c mplog.c mpn2dbl.c
|
||||
mpn2flt.c mpn2ldbl.c mpsqrt.c mptan.c
|
||||
mul.c mul_n.c
|
||||
sincos32.c
|
||||
slowexp.c
|
||||
slowpow.c
|
||||
|
||||
e_acos.c e_acosf.c # e_acosl.c
|
||||
e_acosh.c e_acoshf.c # e_acoshl.c
|
||||
e_asin.c e_asinf.c # e_asinl.c
|
||||
e_atan2.c e_atan2f.c # e_atan2l.c
|
||||
e_atanh.c e_atanhf.c # e_atanhl.c
|
||||
e_cosh.c e_coshf.c # e_coshl.c
|
||||
e_exp.c e_expf.c
|
||||
e_fmod.c e_fmodf.c # e_fmodl.c
|
||||
e_gamma_r.c e_gammaf_r.c
|
||||
e_hypot.c e_hypotf.c # e_hypotl.c
|
||||
e_j0.c e_j0f.c
|
||||
e_j1.c e_j1f.c
|
||||
e_jn.c e_jnf.c
|
||||
e_lgamma_r.c e_lgammaf_r.c
|
||||
e_log.c e_logf.c
|
||||
e_log10.c e_log10f.c
|
||||
e_pow.c e_powf.c # e_powl.c
|
||||
e_rem_pio2f.c
|
||||
e_remainder.c e_remainderf.c # e_remainderl.c
|
||||
e_scalb.c e_scalbf.c # e_scalbl.c
|
||||
e_sinh.c e_sinhf.c # e_sinhl.c
|
||||
k_cos.c k_cosf.c
|
||||
k_sin.c k_sinf.c
|
||||
k_rem_pio2.c k_rem_pio2f.c # k_rem_pio2l.c
|
||||
k_tan.c k_tanf.c
|
||||
s_asinh.c s_asinhf.c # s_asinhl.c
|
||||
s_atan.c s_atanf.c # s_atanl.c
|
||||
s_cbrt.c s_cbrtf.c # s_cbrtl.c
|
||||
s_ceil.c s_ceilf.c # s_ceill.c
|
||||
s_cos.c s_cosf.c
|
||||
s_copysign.c s_copysignf.c
|
||||
s_erf.c s_erff.c # s_erfl.c
|
||||
s_expm1f.c s_expm1.c
|
||||
s_finite.c s_finitef.c # s_finitel.c
|
||||
s_clog.c s_clogf.c # s_clogl.c
|
||||
s_csqrt.c s_csqrtf.c # s_csqrtl.c
|
||||
s_floor.c s_floorf.c # s_floorl.c
|
||||
s_fabs.c s_fabsf.c
|
||||
s_fdim.c s_fdimf.c
|
||||
s_fma.c s_fmaf.c # s_fmal.c
|
||||
s_fmax.c s_fmaxf.c
|
||||
s_fmin.c s_fminf.c
|
||||
s_fpclassify.c s_fpclassifyf.c # s_fpclassifyl.c
|
||||
s_frexp.c s_frexpf.c # s_frexpl.c
|
||||
s_ilogb.c s_ilogbf.c
|
||||
s_isinf.c s_isinff.c # s_isinfl.c
|
||||
s_isnan.c s_isnanf.c
|
||||
s_ldexp.c s_ldexpf.c # s_ldexpl.c
|
||||
s_llrint.c s_llrintf.c # s_llrintl.c
|
||||
s_log1p.c s_log1pf.c
|
||||
s_logb.c s_logbf.c # s_logbl.c
|
||||
s_lrint.c s_lrintf.c # s_lrintl.c
|
||||
s_lround.c s_lroundf.c
|
||||
s_modf.c s_modff.c # s_modfl.c
|
||||
s_nan.c s_nanf.c # s_nanl.c
|
||||
# s_nexttoward.c s_nexttowardf.c s_nexttowardl.c
|
||||
s_round.c s_roundf.c # s_roundl.c
|
||||
s_rint.c s_rintf.c
|
||||
s_scalbn.c s_scalbnf.c # s_scalbnl.c
|
||||
s_signbit.c s_signbitf.c # s_signbitl.c
|
||||
s_significand.c s_significandf.c
|
||||
s_signgam.c
|
||||
s_sin.c s_sinf.c # s_sinl.c
|
||||
s_sincos.c s_sincosf.c
|
||||
s_tan.c s_tanf.c
|
||||
s_tanh.c s_tanhf.c
|
||||
s_trunc.c s_truncf.c
|
||||
t_exp.c
|
||||
w_acos.c w_acosf.c # w_acosl.c
|
||||
w_acosh.c w_acoshf.c # w_acoshl.c
|
||||
w_atan2.c w_atan2f.c # w_atan2l.c
|
||||
w_asin.c w_asinf.c # w_asinl.c
|
||||
w_atanh.c w_atanhf.c # w_atanhl.c
|
||||
w_cosh.c w_coshf.c # w_coshl.c
|
||||
w_drem.c w_dremf.c # w_dreml.c
|
||||
w_exp.c w_expf.c # w_expl.c
|
||||
w_fmod.c w_fmodf.c # w_fmodl.c
|
||||
w_hypot.c w_hypotf.c # w_hypotl.c
|
||||
w_j0.c w_j0f.c
|
||||
w_j1.c w_j1f.c
|
||||
w_jn.c w_jnf.c
|
||||
w_lgamma.c w_lgammaf.c
|
||||
w_lgamma_r.c w_lgammaf_r.c
|
||||
w_log.c w_logf.c # w_logl.c
|
||||
w_log10.c w_log10f.c # w_log10l.c
|
||||
w_pow.c w_powf.c # w_powl.c
|
||||
w_remainder.c w_remainderf.c # w_remainderl.c
|
||||
w_scalb.c w_scalbf.c # w_scalbl.c
|
||||
w_sinh.c w_sinhf.c # w_sinhl.c
|
||||
w_sqrt.c w_sqrtf.c
|
||||
w_tgamma.c w_tgammaf.c # w_tgammal.c
|
||||
;
|
||||
|
||||
local architectureObject ;
|
||||
@@ -93,15 +143,16 @@ for architectureObject in [ MultiArchSubDirSetup arm ] {
|
||||
$(genericSources)
|
||||
;
|
||||
|
||||
MergeObject <$(architecture)>posix_gnu_arch_$(TARGET_ARCH)_others.o :
|
||||
e_sqrt.c
|
||||
e_sqrtf.c
|
||||
MergeObject <$(architecture)>posix_gnu_arch_$(TARGET_ARCH)_other.o :
|
||||
e_sqrt.c e_sqrtf.c # e_sqrtl.c
|
||||
|
||||
feholdexcpt.c fesetenv.c fesetround.c fraiseexcpt.c
|
||||
;
|
||||
|
||||
MergeObjectFromObjects <$(architecture)>posix_gnu_arch_$(TARGET_ARCH).o
|
||||
: :
|
||||
<$(architecture)>posix_gnu_arch_$(TARGET_ARCH)_generic.o
|
||||
<$(architecture)>posix_gnu_arch_$(TARGET_ARCH)_others.o
|
||||
<$(architecture)>posix_gnu_arch_$(TARGET_ARCH)_other.o
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles $(genericSources) ]
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Store current floating-point environment and clear exceptions.
|
||||
Copyright (C) 1997-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <fenv_private.h>
|
||||
#include <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__feholdexcept (fenv_t *envp)
|
||||
{
|
||||
/* Fail if a VFP unit isn't present. */
|
||||
if (!ARM_HAVE_VFP)
|
||||
return 1;
|
||||
|
||||
libc_feholdexcept_vfp (envp);
|
||||
return 0;
|
||||
}
|
||||
libm_hidden_def (__feholdexcept)
|
||||
weak_alias (__feholdexcept, feholdexcept)
|
||||
libm_hidden_weak (feholdexcept)
|
||||
@@ -0,0 +1,66 @@
|
||||
/* Install given floating-point environment.
|
||||
Copyright (C) 2004-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <fenv.h>
|
||||
#include <fpu_control.h>
|
||||
#include <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__fesetenv (const fenv_t *envp)
|
||||
{
|
||||
fpu_control_t fpscr, new_fpscr, updated_fpscr;
|
||||
|
||||
/* Fail if a VFP unit isn't present. */
|
||||
if (!ARM_HAVE_VFP)
|
||||
return 1;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
|
||||
if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV))
|
||||
{
|
||||
/* The new FPSCR is valid, so don't merge the reserved flags. */
|
||||
new_fpscr = envp->__cw;
|
||||
|
||||
/* Write new FPSCR if different (ignoring NZCV flags). */
|
||||
if (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0)
|
||||
_FPU_SETCW (new_fpscr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Preserve the reserved FPSCR flags. */
|
||||
new_fpscr = fpscr & _FPU_RESERVED;
|
||||
new_fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE;
|
||||
|
||||
if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0)
|
||||
{
|
||||
_FPU_SETCW (new_fpscr);
|
||||
|
||||
/* Not all VFP architectures support trapping exceptions, so
|
||||
test whether the relevant bits were set and fail if not. */
|
||||
_FPU_GETCW (updated_fpscr);
|
||||
|
||||
return new_fpscr & ~updated_fpscr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
libm_hidden_def (__fesetenv)
|
||||
weak_alias (__fesetenv, fesetenv)
|
||||
libm_hidden_weak (fesetenv)
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Set current rounding direction.
|
||||
Copyright (C) 2004-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <fenv_private.h>
|
||||
#include <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__fesetround (int round)
|
||||
{
|
||||
/* FE_TONEAREST is the only supported rounding mode
|
||||
if a VFP unit isn't present. */
|
||||
if (!ARM_HAVE_VFP)
|
||||
return (round == FE_TONEAREST) ? 0 : 1;
|
||||
|
||||
if (round & ~_FPU_MASK_RM)
|
||||
return 1;
|
||||
|
||||
libc_fesetround_vfp (round);
|
||||
return 0;
|
||||
}
|
||||
libm_hidden_def (__fesetround)
|
||||
weak_alias (__fesetround, fesetround)
|
||||
libm_hidden_weak (fesetround)
|
||||
@@ -0,0 +1,107 @@
|
||||
/* Raise given exceptions.
|
||||
Copyright (C) 2004-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <fpu_control.h>
|
||||
#include <fenv.h>
|
||||
#include <float.h>
|
||||
#include <arm-features.h>
|
||||
|
||||
|
||||
int
|
||||
__feraiseexcept (int excepts)
|
||||
{
|
||||
/* Fail if a VFP unit isn't present unless nothing needs to be done. */
|
||||
if (!ARM_HAVE_VFP)
|
||||
return (excepts != 0);
|
||||
else
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
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_three = 3.0;
|
||||
|
||||
/* Raise exceptions represented by EXPECTS. But we must raise only
|
||||
one signal at a time. It is important that if the overflow/underflow
|
||||
exception and the inexact exception are given at the same time,
|
||||
the overflow/underflow exception follows the inexact exception. After
|
||||
each exception we read from the fpscr, to force the exception to be
|
||||
raised immediately. */
|
||||
|
||||
/* There are additional complications because this file may be compiled
|
||||
without VFP support enabled, and we also can't assume that the
|
||||
assembler has VFP instructions enabled. To get around this we use the
|
||||
generic coprocessor mnemonics and avoid asking GCC to put float values
|
||||
in VFP registers. */
|
||||
|
||||
/* First: invalid exception. */
|
||||
if (FE_INVALID & excepts)
|
||||
__asm__ __volatile__ (
|
||||
"ldc p10, cr0, %1\n\t" /* flds s0, %1 */
|
||||
"cdp p10, 8, cr0, cr0, cr0, 0\n\t" /* fdivs s0, s0, s0 */
|
||||
"mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
|
||||
: "m" (fp_zero)
|
||||
: "s0");
|
||||
|
||||
/* Next: division by zero. */
|
||||
if (FE_DIVBYZERO & excepts)
|
||||
__asm__ __volatile__ (
|
||||
"ldc p10, cr0, %1\n\t" /* flds s0, %1 */
|
||||
"ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
|
||||
"cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
|
||||
"mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
|
||||
: "m" (fp_one), "m" (fp_zero)
|
||||
: "s0", "s1");
|
||||
|
||||
/* Next: overflow. */
|
||||
if (FE_OVERFLOW & excepts)
|
||||
/* There's no way to raise overflow without also raising inexact. */
|
||||
__asm__ __volatile__ (
|
||||
"ldc p10, cr0, %1\n\t" /* flds s0, %1 */
|
||||
"ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
|
||||
"cdp p10, 3, cr0, cr0, cr0, 1\n\t" /* fadds s0, s0, s1 */
|
||||
"mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
|
||||
: "m" (fp_max), "m" (fp_1e32)
|
||||
: "s0", "s1");
|
||||
|
||||
/* Next: underflow. */
|
||||
if (FE_UNDERFLOW & excepts)
|
||||
__asm__ __volatile__ (
|
||||
"ldc p10, cr0, %1\n\t" /* flds s0, %1 */
|
||||
"ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
|
||||
"cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
|
||||
"mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
|
||||
: "m" (fp_min), "m" (fp_three)
|
||||
: "s0", "s1");
|
||||
|
||||
/* Last: inexact. */
|
||||
if (FE_INEXACT & excepts)
|
||||
__asm__ __volatile__ (
|
||||
"ldc p10, cr0, %1\n\t" /* flds s0, %1 */
|
||||
"ldcl p10, cr0, %2\n\t" /* flds s1, %2 */
|
||||
"cdp p10, 8, cr0, cr0, cr0, 1\n\t" /* fdivs s0, s0, s1 */
|
||||
"mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr) /* fmrx %0, fpscr */
|
||||
: "m" (fp_two), "m" (fp_three)
|
||||
: "s0", "s1");
|
||||
|
||||
/* Success. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
libm_hidden_def (__feraiseexcept)
|
||||
weak_alias (__feraiseexcept, feraiseexcept)
|
||||
libm_hidden_weak (feraiseexcept)
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Macros to test for CPU features on ARM. Generic ARM version.
|
||||
Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _ARM_ARM_FEATURES_H
|
||||
#define _ARM_ARM_FEATURES_H 1
|
||||
|
||||
/* An OS-specific arm-features.h file should define ARM_HAVE_VFP to
|
||||
an appropriate expression for testing at runtime whether the VFP
|
||||
hardware is present. We'll then redefine it to a constant if we
|
||||
know at compile time that we can assume VFP. */
|
||||
|
||||
#ifndef __SOFTFP__
|
||||
/* The compiler is generating VFP instructions, so we're already
|
||||
assuming the hardware exists. */
|
||||
# undef ARM_HAVE_VFP
|
||||
# define ARM_HAVE_VFP 1
|
||||
#endif
|
||||
|
||||
/* An OS-specific arm-features.h file may define ARM_ASSUME_NO_IWMMXT
|
||||
to indicate at compile time that iWMMXt hardware is never present
|
||||
at runtime (or that we never care about its state) and so need not
|
||||
be checked for. */
|
||||
|
||||
/* A more-specific arm-features.h file may define ARM_ALWAYS_BX to indicate
|
||||
that instructions using pc as a destination register must never be used,
|
||||
so a "bx" (or "blx") instruction is always required. */
|
||||
|
||||
/* The log2 of the minimum alignment required for an address that
|
||||
is the target of a computed branch (i.e. a "bx" instruction).
|
||||
A more-specific arm-features.h file may define this to set a more
|
||||
stringent requirement.
|
||||
|
||||
Using this only makes sense for code in ARM mode (where instructions
|
||||
always have a fixed size of four bytes), or for Thumb-mode code that is
|
||||
specifically aligning all the related branch targets to match (since
|
||||
Thumb instructions might be either two or four bytes). */
|
||||
#ifndef ARM_BX_ALIGN_LOG2
|
||||
# define ARM_BX_ALIGN_LOG2 2
|
||||
#endif
|
||||
|
||||
/* An OS-specific arm-features.h file may define ARM_NO_INDEX_REGISTER to
|
||||
indicate that the two-register addressing modes must never be used. */
|
||||
|
||||
#endif /* arm-features.h */
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -12,9 +12,8 @@
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _FENV_H
|
||||
# error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
|
||||
@@ -23,36 +22,69 @@
|
||||
/* Define bits representing exceptions in the FPU status word. */
|
||||
enum
|
||||
{
|
||||
FE_INVALID = 1,
|
||||
#define FE_INVALID FE_INVALID
|
||||
FE_DIVBYZERO = 2,
|
||||
#define FE_DIVBYZERO FE_DIVBYZERO
|
||||
FE_OVERFLOW = 4,
|
||||
#define FE_OVERFLOW FE_OVERFLOW
|
||||
FE_UNDERFLOW = 8,
|
||||
#define FE_UNDERFLOW FE_UNDERFLOW
|
||||
FE_INVALID =
|
||||
#define FE_INVALID 1
|
||||
FE_INVALID,
|
||||
FE_DIVBYZERO =
|
||||
#define FE_DIVBYZERO 2
|
||||
FE_DIVBYZERO,
|
||||
FE_OVERFLOW =
|
||||
#define FE_OVERFLOW 4
|
||||
FE_OVERFLOW,
|
||||
FE_UNDERFLOW =
|
||||
#define FE_UNDERFLOW 8
|
||||
FE_UNDERFLOW,
|
||||
FE_INEXACT =
|
||||
#define FE_INEXACT 16
|
||||
FE_INEXACT,
|
||||
};
|
||||
|
||||
/* Amount to shift by to convert an exception to a mask bit. */
|
||||
#define FE_EXCEPT_SHIFT 16
|
||||
#define FE_EXCEPT_SHIFT 8
|
||||
|
||||
/* All supported exceptions. */
|
||||
#define FE_ALL_EXCEPT \
|
||||
(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)
|
||||
(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
|
||||
|
||||
/* The ARM FPU basically only supports round-to-nearest. Other rounding
|
||||
modes exist, but you have to encode them in the actual instruction. */
|
||||
/* VFP supports all of the four defined rounding modes. */
|
||||
enum
|
||||
{
|
||||
FE_TONEAREST =
|
||||
#define FE_TONEAREST 0
|
||||
FE_TONEAREST,
|
||||
FE_UPWARD =
|
||||
#define FE_UPWARD 0x400000
|
||||
FE_UPWARD,
|
||||
FE_DOWNWARD =
|
||||
#define FE_DOWNWARD 0x800000
|
||||
FE_DOWNWARD,
|
||||
FE_TOWARDZERO =
|
||||
#define FE_TOWARDZERO 0xc00000
|
||||
FE_TOWARDZERO
|
||||
};
|
||||
|
||||
/* Type representing exception flags. */
|
||||
typedef unsigned long int fexcept_t;
|
||||
typedef unsigned int fexcept_t;
|
||||
|
||||
/* Type representing floating-point environment. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned long int __cw;
|
||||
unsigned int __cw;
|
||||
}
|
||||
fenv_t;
|
||||
|
||||
/* If the default argument is used we use this value. */
|
||||
#define FE_DFL_ENV ((fenv_t *) -1l)
|
||||
#define FE_DFL_ENV ((const fenv_t *) -1l)
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Floating-point environment where none of the exceptions are masked. */
|
||||
# define FE_NOMASK_ENV ((const fenv_t *) -2)
|
||||
#endif
|
||||
|
||||
#if 0 // __GLIBC_USE (IEC_60559_BFP_EXT)
|
||||
/* Type representing floating-point control modes. */
|
||||
typedef unsigned int femode_t;
|
||||
|
||||
/* Default floating-point control modes. */
|
||||
# define FE_DFL_MODE ((const femode_t *) -1L)
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
/* Private floating point rounding and exceptions handling. ARM VFP version.
|
||||
Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef FENV_PRIVATE_H
|
||||
#define FENV_PRIVATE_H 1
|
||||
|
||||
#include <fenv.h>
|
||||
#include <fpu_control.h>
|
||||
|
||||
# define __glibc_unlikely(x) __builtin_expect ((x), 0)
|
||||
|
||||
static __always_inline void
|
||||
libc_feholdexcept_vfp (fenv_t *envp)
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
envp->__cw = fpscr;
|
||||
|
||||
/* Clear exception flags and set all exceptions to non-stop. */
|
||||
fpscr &= ~_FPU_MASK_EXCEPT;
|
||||
_FPU_SETCW (fpscr);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_fesetround_vfp (int round)
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
|
||||
/* Set new rounding mode if different. */
|
||||
if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round))
|
||||
_FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_feholdexcept_setround_vfp (fenv_t *envp, int round)
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
envp->__cw = fpscr;
|
||||
|
||||
/* Clear exception flags, set all exceptions to non-stop,
|
||||
and set new rounding mode. */
|
||||
fpscr &= ~(_FPU_MASK_EXCEPT | _FPU_MASK_RM);
|
||||
_FPU_SETCW (fpscr | round);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_feholdsetround_vfp (fenv_t *envp, int round)
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
envp->__cw = fpscr;
|
||||
|
||||
/* Set new rounding mode if different. */
|
||||
if (__glibc_unlikely ((fpscr & _FPU_MASK_RM) != round))
|
||||
_FPU_SETCW ((fpscr & ~_FPU_MASK_RM) | round);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_feresetround_vfp (fenv_t *envp)
|
||||
{
|
||||
fpu_control_t fpscr, round;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
|
||||
/* Check whether rounding modes are different. */
|
||||
round = (envp->__cw ^ fpscr) & _FPU_MASK_RM;
|
||||
|
||||
/* Restore the rounding mode if it was changed. */
|
||||
if (__glibc_unlikely (round != 0))
|
||||
_FPU_SETCW (fpscr ^ round);
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
libc_fetestexcept_vfp (int ex)
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
return fpscr & ex & FE_ALL_EXCEPT;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_fesetenv_vfp (const fenv_t *envp)
|
||||
{
|
||||
fpu_control_t fpscr, new_fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
new_fpscr = envp->__cw;
|
||||
|
||||
/* Write new FPSCR if different (ignoring NZCV flags). */
|
||||
if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
|
||||
_FPU_SETCW (new_fpscr);
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
libc_feupdateenv_test_vfp (const fenv_t *envp, int ex)
|
||||
{
|
||||
fpu_control_t fpscr, new_fpscr;
|
||||
int excepts;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
|
||||
/* Merge current exception flags with the saved fenv. */
|
||||
excepts = fpscr & FE_ALL_EXCEPT;
|
||||
new_fpscr = envp->__cw | excepts;
|
||||
|
||||
/* Write new FPSCR if different (ignoring NZCV flags). */
|
||||
if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
|
||||
_FPU_SETCW (new_fpscr);
|
||||
|
||||
/* Raise the exceptions if enabled in the new FP state. */
|
||||
if (__glibc_unlikely (excepts & (new_fpscr >> FE_EXCEPT_SHIFT)))
|
||||
__feraiseexcept (excepts);
|
||||
|
||||
return excepts & ex;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_feupdateenv_vfp (const fenv_t *envp)
|
||||
{
|
||||
libc_feupdateenv_test_vfp (envp, 0);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_feholdsetround_vfp_ctx (struct rm_ctx *ctx, int r)
|
||||
{
|
||||
fpu_control_t fpscr, round;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
ctx->updated_status = false;
|
||||
ctx->env.__cw = fpscr;
|
||||
|
||||
/* Check whether rounding modes are different. */
|
||||
round = (fpscr ^ r) & _FPU_MASK_RM;
|
||||
|
||||
/* Set the rounding mode if changed. */
|
||||
if (__glibc_unlikely (round != 0))
|
||||
{
|
||||
ctx->updated_status = true;
|
||||
_FPU_SETCW (fpscr ^ round);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_feresetround_vfp_ctx (struct rm_ctx *ctx)
|
||||
{
|
||||
/* Restore the rounding mode if updated. */
|
||||
if (__glibc_unlikely (ctx->updated_status))
|
||||
{
|
||||
fpu_control_t fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
fpscr = (fpscr & ~_FPU_MASK_RM) | (ctx->env.__cw & _FPU_MASK_RM);
|
||||
_FPU_SETCW (fpscr);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
libc_fesetenv_vfp_ctx (struct rm_ctx *ctx)
|
||||
{
|
||||
fpu_control_t fpscr, new_fpscr;
|
||||
|
||||
_FPU_GETCW (fpscr);
|
||||
new_fpscr = ctx->env.__cw;
|
||||
|
||||
/* Write new FPSCR if different (ignoring NZCV flags). */
|
||||
if (__glibc_unlikely (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0))
|
||||
_FPU_SETCW (new_fpscr);
|
||||
}
|
||||
|
||||
#ifndef __SOFTFP__
|
||||
|
||||
# define libc_feholdexcept libc_feholdexcept_vfp
|
||||
# define libc_feholdexceptf libc_feholdexcept_vfp
|
||||
# define libc_feholdexceptl libc_feholdexcept_vfp
|
||||
|
||||
# define libc_fesetround libc_fesetround_vfp
|
||||
# define libc_fesetroundf libc_fesetround_vfp
|
||||
# define libc_fesetroundl libc_fesetround_vfp
|
||||
|
||||
# define libc_feresetround libc_feresetround_vfp
|
||||
# define libc_feresetroundf libc_feresetround_vfp
|
||||
# define libc_feresetroundl libc_feresetround_vfp
|
||||
|
||||
# define libc_feresetround_noex libc_fesetenv_vfp
|
||||
# define libc_feresetround_noexf libc_fesetenv_vfp
|
||||
# define libc_feresetround_noexl libc_fesetenv_vfp
|
||||
|
||||
# define libc_feholdexcept_setround libc_feholdexcept_setround_vfp
|
||||
# define libc_feholdexcept_setroundf libc_feholdexcept_setround_vfp
|
||||
# define libc_feholdexcept_setroundl libc_feholdexcept_setround_vfp
|
||||
|
||||
# define libc_feholdsetround libc_feholdsetround_vfp
|
||||
# define libc_feholdsetroundf libc_feholdsetround_vfp
|
||||
# define libc_feholdsetroundl libc_feholdsetround_vfp
|
||||
|
||||
# define libc_fetestexcept libc_fetestexcept_vfp
|
||||
# define libc_fetestexceptf libc_fetestexcept_vfp
|
||||
# define libc_fetestexceptl libc_fetestexcept_vfp
|
||||
|
||||
# define libc_fesetenv libc_fesetenv_vfp
|
||||
# define libc_fesetenvf libc_fesetenv_vfp
|
||||
# define libc_fesetenvl libc_fesetenv_vfp
|
||||
|
||||
# define libc_feupdateenv libc_feupdateenv_vfp
|
||||
# define libc_feupdateenvf libc_feupdateenv_vfp
|
||||
# define libc_feupdateenvl libc_feupdateenv_vfp
|
||||
|
||||
# define libc_feupdateenv_test libc_feupdateenv_test_vfp
|
||||
# define libc_feupdateenv_testf libc_feupdateenv_test_vfp
|
||||
# define libc_feupdateenv_testl libc_feupdateenv_test_vfp
|
||||
|
||||
/* We have support for rounding mode context. */
|
||||
#define HAVE_RM_CTX 1
|
||||
|
||||
# define libc_feholdsetround_ctx libc_feholdsetround_vfp_ctx
|
||||
# define libc_feresetround_ctx libc_feresetround_vfp_ctx
|
||||
# define libc_feresetround_noex_ctx libc_fesetenv_vfp_ctx
|
||||
|
||||
# define libc_feholdsetroundf_ctx libc_feholdsetround_vfp_ctx
|
||||
# define libc_feresetroundf_ctx libc_feresetround_vfp_ctx
|
||||
# define libc_feresetround_noexf_ctx libc_fesetenv_vfp_ctx
|
||||
|
||||
# define libc_feholdsetroundl_ctx libc_feholdsetround_vfp_ctx
|
||||
# define libc_feresetroundl_ctx libc_feresetround_vfp_ctx
|
||||
# define libc_feresetround_noexl_ctx libc_fesetenv_vfp_ctx
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* FENV_PRIVATE_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/* FPU control word definitions. ARM VFP version.
|
||||
Copyright (C) 2004-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _FPU_CONTROL_H
|
||||
#define _FPU_CONTROL_H
|
||||
|
||||
#if !(defined(_LIBC) && !defined(_LIBC_TEST)) && defined(__SOFTFP__)
|
||||
|
||||
#define _FPU_RESERVED 0xffffffff
|
||||
#define _FPU_DEFAULT 0x00000000
|
||||
typedef unsigned int fpu_control_t;
|
||||
#define _FPU_GETCW(cw) (cw) = 0
|
||||
#define _FPU_SETCW(cw) (void) (cw)
|
||||
extern fpu_control_t __fpu_control;
|
||||
|
||||
#else
|
||||
|
||||
/* masking of interrupts */
|
||||
#define _FPU_MASK_IM 0x00000100 /* invalid operation */
|
||||
#define _FPU_MASK_ZM 0x00000200 /* divide by zero */
|
||||
#define _FPU_MASK_OM 0x00000400 /* overflow */
|
||||
#define _FPU_MASK_UM 0x00000800 /* underflow */
|
||||
#define _FPU_MASK_PM 0x00001000 /* inexact */
|
||||
|
||||
#define _FPU_MASK_NZCV 0xf0000000 /* NZCV flags */
|
||||
#define _FPU_MASK_RM 0x00c00000 /* rounding mode */
|
||||
#define _FPU_MASK_EXCEPT 0x00001f1f /* all exception flags */
|
||||
|
||||
/* Some bits in the FPSCR are not yet defined. They must be preserved when
|
||||
modifying the contents. */
|
||||
#define _FPU_RESERVED 0x00086060
|
||||
#define _FPU_DEFAULT 0x00000000
|
||||
|
||||
/* Default + exceptions enabled. */
|
||||
#define _FPU_IEEE (_FPU_DEFAULT | 0x00001f00)
|
||||
|
||||
/* Type of the control word. */
|
||||
typedef unsigned int fpu_control_t;
|
||||
|
||||
/* Macros for accessing the hardware control word. */
|
||||
#ifdef __SOFTFP__
|
||||
/* This is fmrx %0, fpscr. */
|
||||
# define _FPU_GETCW(cw) \
|
||||
__asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw))
|
||||
/* This is fmxr fpscr, %0. */
|
||||
# define _FPU_SETCW(cw) \
|
||||
__asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw))
|
||||
#else
|
||||
# define _FPU_GETCW(cw) \
|
||||
__asm__ __volatile__ ("vmrs %0, fpscr" : "=r" (cw))
|
||||
# define _FPU_SETCW(cw) \
|
||||
__asm__ __volatile__ ("vmsr fpscr, %0" : : "r" (cw))
|
||||
#endif
|
||||
|
||||
/* Default control word set at startup. */
|
||||
extern fpu_control_t __fpu_control;
|
||||
|
||||
#endif /* __SOFTFP__ */
|
||||
|
||||
#endif /* _FPU_CONTROL_H */
|
||||
Reference in New Issue
Block a user