libc: switch aarch64 to use softfloat functions from compiler_rt

The old definitions in qp.c being all grouped together in one file
causes problems when static linking with libgcc (i.e. cc --static-libgcc)
due to functions like __trunctfdf2 conflicting with libgcc, as seen in
PR 57021

We can also add some missing functions like __fixdfti for converting
a double to an int128_t, the lack of which is currently preventing webkit
from linking on aarch64, as seen in PR 57022

Unclear to me if libc is the right place for these functions, but
we can avoid breaking compatibility right now and maintain the status
quo while avoiding some obvious immediate problems.
nm output for libc shows no functions being removed by this change.
This commit is contained in:
nia 2022-10-05 10:28:19 +00:00
parent 1226d9de07
commit c47c40fb8b
2 changed files with 26 additions and 239 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: qp.c,v 1.3 2018/08/27 16:46:13 ryo Exp $ */
/* $NetBSD: qp.c,v 1.4 2022/10/05 10:28:19 nia Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@ -38,39 +38,12 @@
* invoke them directly since long double arguments are passed in FP/SIMD
* as well as being returned in them while float128 arguments are passed
* in normal registers.
*
* XXX: we're using compiler_rt for this now. Only one function remains
* that is missing from compiler_rt.
*/
long double __addtf3(long double, long double);
long double __divtf3(long double, long double);
long double __modtf3(long double, long double);
long double __multf3(long double, long double);
long double __negtf2(long double);
long double __subtf3(long double, long double);
double __trunctfdf2(long double);
float __trunctfsf2(long double);
long double __extendsftf2(float);
long double __extenddftf2(double);
long double __floatsitf(int32_t);
long double __floatditf(int64_t);
long double __floatunsitf(uint32_t);
long double __floatunditf(uint64_t);
int32_t __fixtfsi(long double);
int64_t __fixtfdi(long double);
uint32_t __fixuntfsi(long double);
uint64_t __fixuntfdi(long double);
#if 0
long double __floattitf(int128_t);
long double __floatuntitf(uint128_t);
int128_t __fixtfti(long double);
uint128_t __fixuntfti(long double);
#endif
union sf_ieee_flt_u {
float fltu_f;
@ -87,42 +60,6 @@ union sf_ieee_ldbl_u {
float128 ldblu_f128;
};
long double
__addtf3(long double ld_a, long double ld_b)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = float128_add(a.ldblu_f128, b.ldblu_f128)
};
return c.ldblu_ld;
}
long double
__divtf3(long double ld_a, long double ld_b)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = float128_div(a.ldblu_f128, b.ldblu_f128)
};
return c.ldblu_ld;
}
long double
__multf3(long double ld_a, long double ld_b)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = float128_mul(a.ldblu_f128, b.ldblu_f128)
};
return c.ldblu_ld;
}
long double
__negtf2(long double ld_a)
{
@ -134,168 +71,3 @@ __negtf2(long double ld_a)
return b.ldblu_ld;
}
long double
__subtf3(long double ld_a, long double ld_b)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = float128_sub(a.ldblu_f128, b.ldblu_f128)
};
return c.ldblu_ld;
}
#if 0
int
__cmptf3(float128 *a, float128 *b)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
if (float128_eq(*a, *b))
return 0;
if (float128_le(*a, *b))
return 1;
return 2;
}
/*
* XXX
*/
int
_Qp_cmpe(float128 *a, float128 *b)
{
return _Qp_cmp(a, b);
}
#endif
float
__trunctfsf2(long double ld_a)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_flt_u c = {
.fltu_f32 = float128_to_float32(a.ldblu_f128),
};
return c.fltu_f;
}
double
__trunctfdf2(long double ld_a)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
const union sf_ieee_dbl_u c = {
.dblu_f64 = float128_to_float64(a.ldblu_f128),
};
return c.dblu_d;
}
int32_t
__fixtfsi(long double ld_a)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
return float128_to_int32_round_to_zero(a.ldblu_f128);
}
int64_t
__fixtfdi(long double ld_a)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
return float128_to_int64_round_to_zero(a.ldblu_f128);
}
#if 0
uint32_t
__fixuntfsi(long double ld_a)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
return float128_to_uint32_round_to_zero(a.ldblu_f128);
}
uint64_t
__fixuntfdi(long double ld_a)
{
const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
return float128_to_uint64_round_to_zero(a.ldblu_f128);
}
#endif
long double
__extendsftf2(float f_a)
{
const union sf_ieee_flt_u a = { .fltu_f = f_a };
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = float32_to_float128(a.fltu_f32)
};
return c.ldblu_ld;
}
long double
__extenddftf2(double d_a)
{
const union sf_ieee_dbl_u a = { .dblu_d = d_a };
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = float64_to_float128(a.dblu_f64)
};
return c.ldblu_ld;
}
long double
__floatunsitf(uint32_t a)
{
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = int64_to_float128(a)
};
return c.ldblu_ld;
}
long double
__floatunditf(uint64_t a)
{
union sf_ieee_ldbl_u c;
const uint64_t msb64 = 1LL << 63;
if (a & msb64) {
static const union sf_ieee_ldbl_u two63 = {
.ldblu_ld = 0x1.0p63
};
c.ldblu_f128 = int64_to_float128(a ^ msb64);
c.ldblu_f128 = float128_add(c.ldblu_f128, two63.ldblu_f128);
} else {
c.ldblu_f128 = int64_to_float128(a);
}
return c.ldblu_ld;
}
long double
__floatsitf(int32_t a)
{
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = int64_to_float128(a)
};
return c.ldblu_ld;
}
long double
__floatditf(int64_t a)
{
const union sf_ieee_ldbl_u c = {
.ldblu_f128 = int64_to_float128(a)
};
return c.ldblu_ld;
}

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.40 2021/06/16 05:21:08 rin Exp $
# $NetBSD: Makefile.inc,v 1.41 2022/10/05 10:28:19 nia Exp $
COMPILER_RT_DIR= ${NETBSDSRCDIR}/sys/external/bsd/compiler_rt
COMPILER_RT_SRCDIR= ${COMPILER_RT_DIR}/dist
@ -133,7 +133,11 @@ GENERIC_SRCS+= \
.endif
.if ${MACHINE_CPU} != "aarch64"
.if ${MACHINE_CPU} == "aarch64"
GENERIC_SRCS+= \
comparetf2.c
.endif
GENERIC_SRCS+= \
fixunsdfti.c \
fixunssfti.c \
@ -145,10 +149,6 @@ GENERIC_SRCS+= \
floatuntidf.c \
floatuntisf.c \
floatuntixf.c
.else
GENERIC_SRCS+= \
comparetf2.c
.endif
# These have h/w instructions which are always used.
.if ${LIBC_MACHINE_ARCH} != "alpha" && ${LIBC_MACHINE_CPU} != "aarch64" \
@ -250,7 +250,22 @@ GENERIC_SRCS+= \
.if ${LIBC_MACHINE_CPU} == "aarch64"
GENERIC_SRCS+= \
clear_cache.c
clear_cache.c \
addtf3.c \
divtf3.c \
multf3.c \
subtf3.c \
trunctfsf2.c \
trunctfdf2.c \
fixdfti.c \
fixtfsi.c \
fixtfdi.c \
extendsftf2.c \
extenddftf2.c \
floatunsitf.c \
floatunditf.c \
floatsitf.c \
floatditf.c
.endif
.if ${LIBC_MACHINE_ARCH} == "powerpc" || ${LIBC_MACHINE_ARCH} == "powerpc64"