Message ID | 20231225103548.1615-4-zhujunxian@oss.cipunited.com |
---|---|
State | New |
Headers | show |
Series | Add hard-float rounding instructions support for MIPS architecture | expand |
On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: /* snip */ > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__ceil) > + .set push > + .set noreorder > + .set noat > +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + ceil.l.d $f0, $f12 No, C23 does not allow this function to raise an INEXACT exception, but ceil.l.d will do so. Such optimizations should be performed in GCC which can be controlled by the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not in Glibc where we cannot know if the programmer wants to deviate from C23.
Junxian Zhu <zhujunxian@oss.cipunited.com> 于 2023年12月25日周一 18:38写道: > From: Junxian Zhu <zhujunxian@oss.cipunited.com> > > Use hardware floating-point rounding instructions to implement roundeven, > trunc, ceil and floor. > > * sysdeps/mips/mips32/Implies: Add source path. > * sysdeps/mips/mips64/Implies: Likewise. > * sysdeps/mips/fpu/Makefile: Newfile. > * sysdeps/mips/fpu/s_ceil.c: Likewise. > * sysdeps/mips/fpu/s_ceil_fpu.S: Likewise. > * sysdeps/mips/fpu/s_ceilf.c: Likewise. > * sysdeps/mips/fpu/s_ceilf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_floor.c: Likewise. > * sysdeps/mips/fpu/s_floor_fpu.S: Likewise. > * sysdeps/mips/fpu/s_floorf.c: Likewise. > * sysdeps/mips/fpu/s_floorf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_roundeven.c: Likewise. > * sysdeps/mips/fpu/s_roundeven_fpu.S: Likewise. > * sysdeps/mips/fpu/s_roundevenf.c: Likewise. > * sysdeps/mips/fpu/s_roundevenf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_trunc.c: Likewise. > * sysdeps/mips/fpu/s_trunc_fpu.S: Likewise. > * sysdeps/mips/fpu/s_truncf.c: Likewise. > * sysdeps/mips/fpu/s_truncf_fpu.S: Likewise. > > Signed-off-by: Rong Zhang <rongrong@oss.cipunited.com> > Signed-off-by: Junxian Zhu <zhujunxian@oss.cipunited.com> > --- > sysdeps/mips/fpu/Makefile | 12 ++++ > sysdeps/mips/fpu/s_ceil.c | 30 ++++++++++ > sysdeps/mips/fpu/s_ceil_fpu.S | 90 +++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_ceilf.c | 30 ++++++++++ > sysdeps/mips/fpu/s_ceilf_fpu.S | 82 ++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_floor.c | 24 ++++++++ > sysdeps/mips/fpu/s_floor_fpu.S | 88 ++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_floorf.c | 24 ++++++++ > sysdeps/mips/fpu/s_floorf_fpu.S | 80 +++++++++++++++++++++++++ > sysdeps/mips/fpu/s_roundeven.c | 24 ++++++++ > sysdeps/mips/fpu/s_roundeven_fpu.S | 87 ++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_roundevenf.c | 24 ++++++++ > sysdeps/mips/fpu/s_roundevenf_fpu.S | 79 +++++++++++++++++++++++++ > sysdeps/mips/fpu/s_trunc.c | 24 ++++++++ > sysdeps/mips/fpu/s_trunc_fpu.S | 84 +++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_truncf.c | 24 ++++++++ > sysdeps/mips/fpu/s_truncf_fpu.S | 76 ++++++++++++++++++++++++ > sysdeps/mips/mips32/Implies | 1 + > sysdeps/mips/mips64/Implies | 1 + > 19 files changed, 884 insertions(+) > create mode 100644 sysdeps/mips/fpu/Makefile > create mode 100644 sysdeps/mips/fpu/s_ceil.c > create mode 100644 sysdeps/mips/fpu/s_ceil_fpu.S > create mode 100644 sysdeps/mips/fpu/s_ceilf.c > create mode 100644 sysdeps/mips/fpu/s_ceilf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_floor.c > create mode 100644 sysdeps/mips/fpu/s_floor_fpu.S > create mode 100644 sysdeps/mips/fpu/s_floorf.c > create mode 100644 sysdeps/mips/fpu/s_floorf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_roundeven.c > create mode 100644 sysdeps/mips/fpu/s_roundeven_fpu.S > create mode 100644 sysdeps/mips/fpu/s_roundevenf.c > create mode 100644 sysdeps/mips/fpu/s_roundevenf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_trunc.c > create mode 100644 sysdeps/mips/fpu/s_trunc_fpu.S > create mode 100644 sysdeps/mips/fpu/s_truncf.c > create mode 100644 sysdeps/mips/fpu/s_truncf_fpu.S > > diff --git a/sysdeps/mips/fpu/Makefile b/sysdeps/mips/fpu/Makefile > new file mode 100644 > index 0000000000..ad537d6bf1 > --- /dev/null > +++ b/sysdeps/mips/fpu/Makefile > @@ -0,0 +1,12 @@ > +ifeq ($(subdir),math) > +sysdep_routines += s_floor_fpu s_floorf_fpu \ > + s_ceil_fpu s_ceilf_fpu \ > + s_trunc_fpu s_truncf_fpu \ > + s_roundeven_fpu s_roundevenf_fpu > + > +libm-sysdep_routines += s_floor_fpu s_floorf_fpu \ > + s_ceil_fpu s_ceilf_fpu \ > + s_trunc_fpu s_truncf_fpu \ > + s_roundeven_fpu s_roundevenf_fpu > + > +endif > diff --git a/sysdeps/mips/fpu/s_ceil.c b/sysdeps/mips/fpu/s_ceil.c > new file mode 100644 > index 0000000000..91a90a70c5 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceil.c > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > __mips_fpr == 64 this condition should not be here. it means fp64. In fact your code should also support fp32 and fpxx. +# include <sysdeps/ieee754/dbl-64/s_ceil.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_ceil_fpu.S b/sysdeps/mips/fpu/s_ceil_fpu.S > new file mode 100644 > index 0000000000..13d4f85ad3 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceil_fpu.S > @@ -0,0 +1,90 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__ceil) > + .set push > + .set noreorder > + .set noat > +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + ceil.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__ceil) > +libm_alias_double (__ceil, ceil) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_ceilf.c b/sysdeps/mips/fpu/s_ceilf.c > new file mode 100644 > index 0000000000..a7f81c7539 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceilf.c > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_ceilf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_ceilf_fpu.S > b/sysdeps/mips/fpu/s_ceilf_fpu.S > new file mode 100644 > index 0000000000..7952894f73 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceilf_fpu.S > @@ -0,0 +1,82 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__ceilf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + ceil.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__ceilf) > +libm_alias_float (__ceil, ceil) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_floor.c b/sysdeps/mips/fpu/s_floor.c > new file mode 100644 > index 0000000000..4b43dc9ad9 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floor.c > @@ -0,0 +1,24 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/dbl-64/s_floor.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_floor_fpu.S > b/sysdeps/mips/fpu/s_floor_fpu.S > new file mode 100644 > index 0000000000..fda661fd3a > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floor_fpu.S > @@ -0,0 +1,88 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__floor) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + floor.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + li AT, 0xbff # used by SMALL_NEGATIVE > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__floor) > +libm_alias_double (__floor, floor) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_floorf.c b/sysdeps/mips/fpu/s_floorf.c > new file mode 100644 > index 0000000000..30cfda7820 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floorf.c > @@ -0,0 +1,24 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_floorf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_floorf_fpu.S > b/sysdeps/mips/fpu/s_floorf_fpu.S > new file mode 100644 > index 0000000000..8edd234dbc > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floorf_fpu.S > @@ -0,0 +1,80 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__floorf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + floor.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + li AT, 0xbff # used by SMALL_NEGATIVE > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__floorf) > +libm_alias_float (__floor, floor) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_roundeven.c > b/sysdeps/mips/fpu/s_roundeven.c > new file mode 100644 > index 0000000000..dace85a70b > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundeven.c > @@ -0,0 +1,24 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/dbl-64/s_roundeven.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_roundeven_fpu.S > b/sysdeps/mips/fpu/s_roundeven_fpu.S > new file mode 100644 > index 0000000000..aef6434886 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundeven_fpu.S > @@ -0,0 +1,87 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__roundeven) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + round.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__roundeven) > +libm_alias_double (__roundeven, roundeven) > + > +#endif > diff --git a/sysdeps/mips/fpu/s_roundevenf.c > b/sysdeps/mips/fpu/s_roundevenf.c > new file mode 100644 > index 0000000000..5bb35901db > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundevenf.c > @@ -0,0 +1,24 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_roundevenf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_roundevenf_fpu.S > b/sysdeps/mips/fpu/s_roundevenf_fpu.S > new file mode 100644 > index 0000000000..e946e50d8f > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundevenf_fpu.S > @@ -0,0 +1,79 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__roundevenf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + round.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__roundevenf) > +libm_alias_float (__roundeven, roundeven) > + > +#endif > diff --git a/sysdeps/mips/fpu/s_trunc.c b/sysdeps/mips/fpu/s_trunc.c > new file mode 100644 > index 0000000000..3865026c70 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_trunc.c > @@ -0,0 +1,24 @@ > +/* Truncate argument to nearest integral value not larger than the > argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/dbl-64/s_trunc.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_trunc_fpu.S > b/sysdeps/mips/fpu/s_trunc_fpu.S > new file mode 100644 > index 0000000000..3a7947507f > --- /dev/null > +++ b/sysdeps/mips/fpu/s_trunc_fpu.S > @@ -0,0 +1,84 @@ > +/* Truncate argument to nearest integral value not larger than the > argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__trunc) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + trunc.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__trunc) > +libm_alias_double (__trunc, trunc) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_truncf.c b/sysdeps/mips/fpu/s_truncf.c > new file mode 100644 > index 0000000000..59ef17bf74 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_truncf.c > @@ -0,0 +1,24 @@ > +/* Truncate argument to nearest integral value not larger than the > argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_truncf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_truncf_fpu.S > b/sysdeps/mips/fpu/s_truncf_fpu.S > new file mode 100644 > index 0000000000..1878d88e3c > --- /dev/null > +++ b/sysdeps/mips/fpu/s_truncf_fpu.S > @@ -0,0 +1,76 @@ > +/* Truncate argument to nearest integral value not larger than the > argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && > __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__truncf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + trunc.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__truncf) > +libm_alias_float (__trunc, trunc) > + > +#endif > + > diff --git a/sysdeps/mips/mips32/Implies b/sysdeps/mips/mips32/Implies > index 6473f2517c..71b3678c6c 100644 > --- a/sysdeps/mips/mips32/Implies > +++ b/sysdeps/mips/mips32/Implies > @@ -1,3 +1,4 @@ > +mips/fpu > mips/ieee754 > mips > wordsize-32 > diff --git a/sysdeps/mips/mips64/Implies b/sysdeps/mips/mips64/Implies > index 826ff1541f..8885ebd564 100644 > --- a/sysdeps/mips/mips64/Implies > +++ b/sysdeps/mips/mips64/Implies > @@ -1,4 +1,5 @@ > # MIPS uses IEEE 754 floating point. > +mips/fpu > mips/ieee754 > ieee754/flt-32 > ieee754/dbl-64 > -- > 2.43.0.windows.1 >
在 2023/12/25 18:51, Xi Ruoyao 写道: > On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: > > /* snip */ > >> +/* >> + * ceil(x) >> + * Return x rounded toward -inf to integral value >> + * Method: >> + * Bit twiddling. >> + */ >> + >> +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) >> +#include <sys/regdef.h> >> +#include <sysdep.h> >> +#include <libm-alias-double.h> >> + >> +ENTRY(__ceil) >> + .set push >> + .set noreorder >> + .set noat >> +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp >> +#if __mips == 64 >> + dmfc1 a0, $f12 # assign int64 >> +#else >> + mfhc1 a0, $f12 # assign int64 >> +#endif >> + cfc1 t0, $f26 >> + ceil.l.d $f0, $f12 > No, C23 does not allow this function to raise an INEXACT exception, but > ceil.l.d will do so. > > Such optimizations should be performed in GCC which can be controlled by > the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not > in Glibc where we cannot know if the programmer wants to deviate from > C23. The cfc1 instruction will backup float point exception status before running ceil.l.d, and the following ctc1 will restore float point exception status to avoid INEXACT exception raised by ceil.l.d. It's the same way like what have been done in s_ceil.S for i386.
在 2023/12/25 20:36, YunQiang Su 写道: > > > Junxian Zhu <zhujunxian@oss.cipunited.com> 于 2023年12月25日周一 > 18:38写道: > > From: Junxian Zhu <zhujunxian@oss.cipunited.com> > > Use hardware floating-point rounding instructions to implement > roundeven, trunc, ceil and floor. > > * sysdeps/mips/mips32/Implies: Add source path. > * sysdeps/mips/mips64/Implies: Likewise. > * sysdeps/mips/fpu/Makefile: Newfile. > * sysdeps/mips/fpu/s_ceil.c: Likewise. > * sysdeps/mips/fpu/s_ceil_fpu.S: Likewise. > * sysdeps/mips/fpu/s_ceilf.c: Likewise. > * sysdeps/mips/fpu/s_ceilf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_floor.c: Likewise. > * sysdeps/mips/fpu/s_floor_fpu.S: Likewise. > * sysdeps/mips/fpu/s_floorf.c: Likewise. > * sysdeps/mips/fpu/s_floorf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_roundeven.c: Likewise. > * sysdeps/mips/fpu/s_roundeven_fpu.S: Likewise. > * sysdeps/mips/fpu/s_roundevenf.c: Likewise. > * sysdeps/mips/fpu/s_roundevenf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_trunc.c: Likewise. > * sysdeps/mips/fpu/s_trunc_fpu.S: Likewise. > * sysdeps/mips/fpu/s_truncf.c: Likewise. > * sysdeps/mips/fpu/s_truncf_fpu.S: Likewise. > > Signed-off-by: Rong Zhang <rongrong@oss.cipunited.com> > Signed-off-by: Junxian Zhu <zhujunxian@oss.cipunited.com> > --- > sysdeps/mips/fpu/Makefile | 12 ++++ > sysdeps/mips/fpu/s_ceil.c | 30 ++++++++++ > sysdeps/mips/fpu/s_ceil_fpu.S | 90 > +++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_ceilf.c | 30 ++++++++++ > sysdeps/mips/fpu/s_ceilf_fpu.S | 82 ++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_floor.c | 24 ++++++++ > sysdeps/mips/fpu/s_floor_fpu.S | 88 ++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_floorf.c | 24 ++++++++ > sysdeps/mips/fpu/s_floorf_fpu.S | 80 +++++++++++++++++++++++++ > sysdeps/mips/fpu/s_roundeven.c | 24 ++++++++ > sysdeps/mips/fpu/s_roundeven_fpu.S | 87 ++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_roundevenf.c | 24 ++++++++ > sysdeps/mips/fpu/s_roundevenf_fpu.S | 79 +++++++++++++++++++++++++ > sysdeps/mips/fpu/s_trunc.c | 24 ++++++++ > sysdeps/mips/fpu/s_trunc_fpu.S | 84 +++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_truncf.c | 24 ++++++++ > sysdeps/mips/fpu/s_truncf_fpu.S | 76 ++++++++++++++++++++++++ > sysdeps/mips/mips32/Implies | 1 + > sysdeps/mips/mips64/Implies | 1 + > 19 files changed, 884 insertions(+) > create mode 100644 sysdeps/mips/fpu/Makefile > create mode 100644 sysdeps/mips/fpu/s_ceil.c > create mode 100644 sysdeps/mips/fpu/s_ceil_fpu.S > create mode 100644 sysdeps/mips/fpu/s_ceilf.c > create mode 100644 sysdeps/mips/fpu/s_ceilf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_floor.c > create mode 100644 sysdeps/mips/fpu/s_floor_fpu.S > create mode 100644 sysdeps/mips/fpu/s_floorf.c > create mode 100644 sysdeps/mips/fpu/s_floorf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_roundeven.c > create mode 100644 sysdeps/mips/fpu/s_roundeven_fpu.S > create mode 100644 sysdeps/mips/fpu/s_roundevenf.c > create mode 100644 sysdeps/mips/fpu/s_roundevenf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_trunc.c > create mode 100644 sysdeps/mips/fpu/s_trunc_fpu.S > create mode 100644 sysdeps/mips/fpu/s_truncf.c > create mode 100644 sysdeps/mips/fpu/s_truncf_fpu.S > > diff --git a/sysdeps/mips/fpu/Makefile b/sysdeps/mips/fpu/Makefile > new file mode 100644 > index 0000000000..ad537d6bf1 > --- /dev/null > +++ b/sysdeps/mips/fpu/Makefile > @@ -0,0 +1,12 @@ > +ifeq ($(subdir),math) > +sysdep_routines += s_floor_fpu s_floorf_fpu \ > + s_ceil_fpu s_ceilf_fpu \ > + s_trunc_fpu s_truncf_fpu \ > + s_roundeven_fpu s_roundevenf_fpu > + > +libm-sysdep_routines += s_floor_fpu s_floorf_fpu \ > + s_ceil_fpu s_ceilf_fpu \ > + s_trunc_fpu s_truncf_fpu \ > + s_roundeven_fpu s_roundevenf_fpu > + > +endif > diff --git a/sysdeps/mips/fpu/s_ceil.c b/sysdeps/mips/fpu/s_ceil.c > new file mode 100644 > index 0000000000..91a90a70c5 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceil.c > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > > > __mips_fpr == 64 > this condition should not be here. > it means fp64. > In fact your code should also support fp32 and fpxx. > > +# include <sysdeps/ieee754/dbl-64/s_ceil.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_ceil_fpu.S > b/sysdeps/mips/fpu/s_ceil_fpu.S > new file mode 100644 > index 0000000000..13d4f85ad3 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceil_fpu.S > @@ -0,0 +1,90 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__ceil) > + .set push > + .set noreorder > + .set noat > +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + ceil.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__ceil) > +libm_alias_double (__ceil, ceil) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_ceilf.c b/sysdeps/mips/fpu/s_ceilf.c > new file mode 100644 > index 0000000000..a7f81c7539 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceilf.c > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_ceilf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_ceilf_fpu.S > b/sysdeps/mips/fpu/s_ceilf_fpu.S > new file mode 100644 > index 0000000000..7952894f73 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceilf_fpu.S > @@ -0,0 +1,82 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__ceilf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + ceil.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__ceilf) > +libm_alias_float (__ceil, ceil) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_floor.c b/sysdeps/mips/fpu/s_floor.c > new file mode 100644 > index 0000000000..4b43dc9ad9 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floor.c > @@ -0,0 +1,24 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/dbl-64/s_floor.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_floor_fpu.S > b/sysdeps/mips/fpu/s_floor_fpu.S > new file mode 100644 > index 0000000000..fda661fd3a > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floor_fpu.S > @@ -0,0 +1,88 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__floor) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + floor.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + li AT, 0xbff # used by SMALL_NEGATIVE > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__floor) > +libm_alias_double (__floor, floor) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_floorf.c b/sysdeps/mips/fpu/s_floorf.c > new file mode 100644 > index 0000000000..30cfda7820 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floorf.c > @@ -0,0 +1,24 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_floorf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_floorf_fpu.S > b/sysdeps/mips/fpu/s_floorf_fpu.S > new file mode 100644 > index 0000000000..8edd234dbc > --- /dev/null > +++ b/sysdeps/mips/fpu/s_floorf_fpu.S > @@ -0,0 +1,80 @@ > +/* Round double to integer away from zero. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__floorf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + floor.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + li AT, 0xbff # used by SMALL_NEGATIVE > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__floorf) > +libm_alias_float (__floor, floor) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_roundeven.c > b/sysdeps/mips/fpu/s_roundeven.c > new file mode 100644 > index 0000000000..dace85a70b > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundeven.c > @@ -0,0 +1,24 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/dbl-64/s_roundeven.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_roundeven_fpu.S > b/sysdeps/mips/fpu/s_roundeven_fpu.S > new file mode 100644 > index 0000000000..aef6434886 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundeven_fpu.S > @@ -0,0 +1,87 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__roundeven) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + round.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__roundeven) > +libm_alias_double (__roundeven, roundeven) > + > +#endif > diff --git a/sysdeps/mips/fpu/s_roundevenf.c > b/sysdeps/mips/fpu/s_roundevenf.c > new file mode 100644 > index 0000000000..5bb35901db > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundevenf.c > @@ -0,0 +1,24 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_roundevenf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_roundevenf_fpu.S > b/sysdeps/mips/fpu/s_roundevenf_fpu.S > new file mode 100644 > index 0000000000..e946e50d8f > --- /dev/null > +++ b/sysdeps/mips/fpu/s_roundevenf_fpu.S > @@ -0,0 +1,79 @@ > +/* Round to nearest integer value, rounding halfway cases to even. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__roundevenf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + round.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: > + mfhc1 t1, $f0 > + bnez t1, SMALL_POSITIVE # sign == 0 > + nop > + > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__roundevenf) > +libm_alias_float (__roundeven, roundeven) > + > +#endif > diff --git a/sysdeps/mips/fpu/s_trunc.c b/sysdeps/mips/fpu/s_trunc.c > new file mode 100644 > index 0000000000..3865026c70 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_trunc.c > @@ -0,0 +1,24 @@ > +/* Truncate argument to nearest integral value not larger than > the argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/dbl-64/s_trunc.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_trunc_fpu.S > b/sysdeps/mips/fpu/s_trunc_fpu.S > new file mode 100644 > index 0000000000..3a7947507f > --- /dev/null > +++ b/sysdeps/mips/fpu/s_trunc_fpu.S > @@ -0,0 +1,84 @@ > +/* Truncate argument to nearest integral value not larger than > the argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-double.h> > + > +ENTRY(__trunc) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > +#if __mips == 64 > + dmfc1 a0, $f12 # assign int64 > +#else > + mfhc1 a0, $f12 # assign int64 > +#endif > + cfc1 t0, $f26 > + trunc.l.d $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 52, 11 # assign exp > +#else > + dsrl a3, a0, 52 > + andi a3, a3, 0x7ff > +#endif > +#else > + ext a3, a0, 20, 11 # assign exp > +#endif > + sltiu AT, a3, 1023 > + bnez AT, SMALL # exp < 1023 > + ctc1 t0, $f26 > + sltiu AT, a3, 1023+54 > + beqz AT, BIG # exp >= 1023+54 > + li AT, 0x7ff > + > + jr ra > + cvt.d.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac > + nop > +NAN_INF: > + jr ra > + add.d $f0, $f12, $f12 # return double + double > +SMALL: > +#if __mips == 64 > + dsrl a2, a0, 63 > +#else > + srl a2, a0, 31 > +#endif > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.d $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.d.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.d $f0, $f12 > + .set pop > + > +END (__trunc) > +libm_alias_double (__trunc, trunc) > + > +#endif > + > diff --git a/sysdeps/mips/fpu/s_truncf.c b/sysdeps/mips/fpu/s_truncf.c > new file mode 100644 > index 0000000000..59ef17bf74 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_truncf.c > @@ -0,0 +1,24 @@ > +/* Truncate argument to nearest integral value not larger than > the argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > +# include <sysdeps/ieee754/flt-32/s_truncf.c> > + > +#endif > diff --git a/sysdeps/mips/fpu/s_truncf_fpu.S > b/sysdeps/mips/fpu/s_truncf_fpu.S > new file mode 100644 > index 0000000000..1878d88e3c > --- /dev/null > +++ b/sysdeps/mips/fpu/s_truncf_fpu.S > @@ -0,0 +1,76 @@ > +/* Truncate argument to nearest integral value not larger than > the argument. > + Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips > == 32 && __mips_isa_rev > 1) || __mips == 64)) > +#include <sys/regdef.h> > +#include <sysdep.h> > +#include <libm-alias-float.h> > + > +ENTRY(__truncf) > + .set push > + .set noreorder > + .set noat > +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp > + mfc1 a0, $f12 # assign int32 > + cfc1 t0, $f26 > + trunc.l.s $f0, $f12 > +#if __mips == 64 > +#if __mips_isa_rev > 1 > + dext a3, a0, 23, 8 # assign exp > +#else > + dsrl a3, a0, 23 > + andi a3, a3, 0x1ff > +#endif > +#else > + ext a3, a0, 23, 8 # assign exp > +#endif > + sltiu AT, a3, 127 > + bnez AT, SMALL # exp < 127 > + ctc1 t0, $f26 > + sltiu AT, a3, 127+25 > + beqz AT, BIG # exp >= 127+25 > + li AT, 0xff > + > + jr ra > + cvt.s.l $f0, $f0 > +BIG: > + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac > + nop > +NAN_INF: > + jr ra > + add.s $f0, $f12, $f12 # return double + double > +SMALL: > + srl a2, a0, 31 > + beqz a2, SMALL_POSITIVE # sign == 0 > + nop > +SMALL_NEGATIVE: # return -0.0 > + jr ra > + neg.s $f0, $f0 > +SMALL_POSITIVE: > + jr ra > + cvt.s.l $f0, $f0 > +RETURN_AS_IS: > + jr ra > + mov.s $f0, $f12 > + .set pop > + > +END (__truncf) > +libm_alias_float (__trunc, trunc) > + > +#endif > + > diff --git a/sysdeps/mips/mips32/Implies b/sysdeps/mips/mips32/Implies > index 6473f2517c..71b3678c6c 100644 > --- a/sysdeps/mips/mips32/Implies > +++ b/sysdeps/mips/mips32/Implies > @@ -1,3 +1,4 @@ > +mips/fpu > mips/ieee754 > mips > wordsize-32 > diff --git a/sysdeps/mips/mips64/Implies b/sysdeps/mips/mips64/Implies > index 826ff1541f..8885ebd564 100644 > --- a/sysdeps/mips/mips64/Implies > +++ b/sysdeps/mips/mips64/Implies > @@ -1,4 +1,5 @@ > # MIPS uses IEEE 754 floating point. > +mips/fpu > mips/ieee754 > ieee754/flt-32 > ieee754/dbl-64 > -- > 2.43.0.windows.1 > According to restrictions about rounding instructions in MIPS instructions manual, "The result of this instruction is UNPREDICTABLE if the processor is executing in the FR=0 32-bit FPU register model; it is predictable if executing on a 64-bit FPU in the FR=1 mode, but not with FR=0, and not on a 32-bit FPU.". It means that such MIPS rounding instruction could only work correct in the FR=1 mode, and fp64 is the only ABI can make sure MIPS FPU running at FR=1 mode. If we support fp32 or fpxx, the result will be UNPREDICTABLE.
On Tue, 2023-12-26 at 10:37 +0800, Junxian Zhu wrote: > 在 2023/12/25 18:51, Xi Ruoyao 写道: > > On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: > > > > /* snip */ > > > > > +/* > > > + * ceil(x) > > > + * Return x rounded toward -inf to integral value > > > + * Method: > > > + * Bit twiddling. > > > + */ > > > + > > > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > > > +#include <sys/regdef.h> > > > +#include <sysdep.h> > > > +#include <libm-alias-double.h> > > > + > > > +ENTRY(__ceil) > > > + .set push > > > + .set noreorder > > > + .set noat > > > +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > > > +#if __mips == 64 > > > + dmfc1 a0, $f12 # assign int64 > > > +#else > > > + mfhc1 a0, $f12 # assign int64 > > > +#endif > > > + cfc1 t0, $f26 > > > + ceil.l.d $f0, $f12 > > No, C23 does not allow this function to raise an INEXACT exception, but > > ceil.l.d will do so. > > > > Such optimizations should be performed in GCC which can be controlled by > > the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not > > in Glibc where we cannot know if the programmer wants to deviate from > > C23. > > The cfc1 instruction will backup float point exception status before > running ceil.l.d, and the following ctc1 will restore float point > exception status to avoid INEXACT exception raised by ceil.l.d. It's the > same way like what have been done in s_ceil.S for i386. Still incorrect because when the Enable field of FCSR contains INEXACT a SIGFPE will be immediately delivered and there is no way to recover. A demonstration: #define _GNU_SOURCE #include <stdio.h> #include <fenv.h> int main() { printf("%d\n", feenableexcept(FE_INEXACT)); double data = 114.514; long control; asm("cfc1\t%1,$f26\n\t" "ceil.l.d\t%0,%0\n\t" "cvt.d.l\t%0,%0\n\t" "ctc1\t%1,$f26": "+f"(data), "=r"(control)); printf("%.15f\n", data); return 0; } On i386 the fnstenv instruction also masks out all the FP exceptions so this is not a problem. See commit 26b0bf96000a.
On 26/12/23 05:29, Xi Ruoyao wrote: > On Tue, 2023-12-26 at 10:37 +0800, Junxian Zhu wrote: >> 在 2023/12/25 18:51, Xi Ruoyao 写道: >>> On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: >>> >>> /* snip */ >>> >>>> +/* >>>> + * ceil(x) >>>> + * Return x rounded toward -inf to integral value >>>> + * Method: >>>> + * Bit twiddling. >>>> + */ >>>> + >>>> +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) >>>> +#include <sys/regdef.h> >>>> +#include <sysdep.h> >>>> +#include <libm-alias-double.h> >>>> + >>>> +ENTRY(__ceil) >>>> + .set push >>>> + .set noreorder >>>> + .set noat >>>> +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp >>>> +#if __mips == 64 >>>> + dmfc1 a0, $f12 # assign int64 >>>> +#else >>>> + mfhc1 a0, $f12 # assign int64 >>>> +#endif >>>> + cfc1 t0, $f26 >>>> + ceil.l.d $f0, $f12 >>> No, C23 does not allow this function to raise an INEXACT exception, but >>> ceil.l.d will do so. >>> >>> Such optimizations should be performed in GCC which can be controlled by >>> the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not >>> in Glibc where we cannot know if the programmer wants to deviate from >>> C23. >> >> The cfc1 instruction will backup float point exception status before >> running ceil.l.d, and the following ctc1 will restore float point >> exception status to avoid INEXACT exception raised by ceil.l.d. It's the >> same way like what have been done in s_ceil.S for i386. > > Still incorrect because when the Enable field of FCSR contains INEXACT a > SIGFPE will be immediately delivered and there is no way to recover. A > demonstration: > > #define _GNU_SOURCE > #include <stdio.h> > #include <fenv.h> > > int main() > { > printf("%d\n", feenableexcept(FE_INEXACT)); > > double data = 114.514; > long control; > asm("cfc1\t%1,$f26\n\t" > "ceil.l.d\t%0,%0\n\t" > "cvt.d.l\t%0,%0\n\t" > "ctc1\t%1,$f26": "+f"(data), "=r"(control)); > printf("%.15f\n", data); > return 0; > } > > On i386 the fnstenv instruction also masks out all the FP exceptions so > this is not a problem. See commit 26b0bf96000a. > And we lack proper tests for ceil, floor, round and trunc similar to test-nearbyint-except2.c to check if the implementation does not wrongly raise inexact floating point exception. Also, I see no point in implementing this optimizations with assembly where a C implementation would be way simpler and generate similar code. Similar to what I did for powerpc with sysdeps/powerpc/fpu/round_to_integer.h, I implemented a similar approach for MIPS [1]. The resulting code should be similar to the assembly implementation, taking in consideration the correct fix to save/restore floating-point exceptions. I did see no math regression on cfarm23 with a glibc built with -mabi=64 -mips64r2. As a side note, it seems that x86 long double implementation are not fully c23 conformant (as they are wrongly raising inexact exception if the exception is already set). [1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/mips-hw-fp-round
On Tue, 2023-12-26 at 17:12 -0300, Adhemerval Zanella Netto wrote: > Also, I see no point in implementing this optimizations with assembly where > a C implementation would be way simpler and generate similar code. Similar > to what I did for powerpc with sysdeps/powerpc/fpu/round_to_integer.h, I > implemented a similar approach for MIPS [1]. The resulting code should be > similar to the assembly implementation, taking in consideration the correct > fix to save/restore floating-point exceptions. I did see no math regression > on cfarm23 with a glibc built with -mabi=64 -mips64r2. Is there a micro-benchmark result on the cfarm machine? AFAIK the FCSR setting instruction may be much more slower than normal instructions, so I'm not sure if this is really a win.
On Wed, 2023-12-27 at 05:50 +0800, Xi Ruoyao wrote: > On Tue, 2023-12-26 at 17:12 -0300, Adhemerval Zanella Netto wrote: > > Also, I see no point in implementing this optimizations with assembly where > > a C implementation would be way simpler and generate similar code. Similar > > to what I did for powerpc with sysdeps/powerpc/fpu/round_to_integer.h, I > > implemented a similar approach for MIPS [1]. The resulting code should be > > similar to the assembly implementation, taking in consideration the correct > > fix to save/restore floating-point exceptions. I did see no math regression > > on cfarm23 with a glibc built with -mabi=64 -mips64r2. > > Is there a micro-benchmark result on the cfarm machine? AFAIK the FCSR > setting instruction may be much more slower than normal instructions, so > I'm not sure if this is really a win. Add Jiaxun who knows MIPS much better than me.
On 26/12/23 19:50, Xi Ruoyao wrote: > On Wed, 2023-12-27 at 05:50 +0800, Xi Ruoyao wrote: >> On Tue, 2023-12-26 at 17:12 -0300, Adhemerval Zanella Netto wrote: >>> Also, I see no point in implementing this optimizations with assembly where >>> a C implementation would be way simpler and generate similar code. Similar >>> to what I did for powerpc with sysdeps/powerpc/fpu/round_to_integer.h, I >>> implemented a similar approach for MIPS [1]. The resulting code should be >>> similar to the assembly implementation, taking in consideration the correct >>> fix to save/restore floating-point exceptions. I did see no math regression >>> on cfarm23 with a glibc built with -mabi=64 -mips64r2. >> >> Is there a micro-benchmark result on the cfarm machine? AFAIK the FCSR >> setting instruction may be much more slower than normal instructions, so >> I'm not sure if this is really a win. > > Add Jiaxun who knows MIPS much better than me. > This is a good question, we do have a trunc one which should give us a hint whether this strategy might shows any performance gain. At least with cfarm230 (Cavium Octeon III V0.2 FPU V0.0) my version is actually worse than the generic one: - Using master/generic: $ ./ld.so --library-path . ./bench-trunc "trunc": { "": { "duration": 9.83902e+08, "iterations": 4.2864e+07, "max": 10027.9, "min": 21.329, "mean": 22.954 } } - Using trunc.l.d: $ ./ld.so --library-path . ./bench-trunc "trunc": { "": { "duration": 9.91892e+08, "iterations": 2.2458e+07, "max": 10048.9, "min": 38.326, "mean": 44.1666 } } The system does not have perf, but I guess that libc_fesetenv_mips is really bad performance-wise since it requires to read the current state to flush the fpu pipeline and the set the previous one (which is ends up being two cfc1). In any case I updated my branch [1] with single float implementation, if any wants to experiment with it. At least this experiment raised the issue that some ceil, floor, round, and/or trunc implementation might still raising inexact floating point exceptions due lacking of proper testing. PS: I had to disable the vDSO on this system since clock_gettime was returning bogus value that make the bench tests unusable. [1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/mips-hw-fp-round
On Mon, 25 Dec 2023, Junxian Zhu wrote: > diff --git a/sysdeps/mips/mips32/Implies b/sysdeps/mips/mips32/Implies > index 6473f2517c..71b3678c6c 100644 > --- a/sysdeps/mips/mips32/Implies > +++ b/sysdeps/mips/mips32/Implies > @@ -1,3 +1,4 @@ > +mips/fpu > mips/ieee754 > mips > wordsize-32 > diff --git a/sysdeps/mips/mips64/Implies b/sysdeps/mips/mips64/Implies > index 826ff1541f..8885ebd564 100644 > --- a/sysdeps/mips/mips64/Implies > +++ b/sysdeps/mips/mips64/Implies > @@ -1,4 +1,5 @@ > # MIPS uses IEEE 754 floating point. > +mips/fpu > mips/ieee754 > ieee754/flt-32 > ieee754/dbl-64 These changes are clearly incorrect, as they would cause mips/fpu/ to be used for soft-float. The fpu/ directories are selected automatically for hard-float, and must not be used for soft-float. I'm guessing you're motivated by some ordering issue that results in the ieee754/ directories ending up being used before mips/fpu/. I'm not sure of the best way to avoid such an ordering issue (noting that the ieee754/ directories go in Implies separately for mips32 and mips64 because only mips64 uses ldbl-128), but e.g. #includes like in sysdeps/mips/mips64/n32/fpu/s_fma.c should work if you can't get the preferred sysdeps directory ordering.
在 2023/12/26 16:29, Xi Ruoyao 写道: > On Tue, 2023-12-26 at 10:37 +0800, Junxian Zhu wrote: >> 在 2023/12/25 18:51, Xi Ruoyao 写道: >>> On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: >>> >>> /* snip */ >>> >>>> +/* >>>> + * ceil(x) >>>> + * Return x rounded toward -inf to integral value >>>> + * Method: >>>> + * Bit twiddling. >>>> + */ >>>> + >>>> +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) >>>> +#include <sys/regdef.h> >>>> +#include <sysdep.h> >>>> +#include <libm-alias-double.h> >>>> + >>>> +ENTRY(__ceil) >>>> + .set push >>>> + .set noreorder >>>> + .set noat >>>> +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp >>>> +#if __mips == 64 >>>> + dmfc1 a0, $f12 # assign int64 >>>> +#else >>>> + mfhc1 a0, $f12 # assign int64 >>>> +#endif >>>> + cfc1 t0, $f26 >>>> + ceil.l.d $f0, $f12 >>> No, C23 does not allow this function to raise an INEXACT exception, but >>> ceil.l.d will do so. >>> >>> Such optimizations should be performed in GCC which can be controlled by >>> the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not >>> in Glibc where we cannot know if the programmer wants to deviate from >>> C23. >> The cfc1 instruction will backup float point exception status before >> running ceil.l.d, and the following ctc1 will restore float point >> exception status to avoid INEXACT exception raised by ceil.l.d. It's the >> same way like what have been done in s_ceil.S for i386. > Still incorrect because when the Enable field of FCSR contains INEXACT a > SIGFPE will be immediately delivered and there is no way to recover. A > demonstration: > > #define _GNU_SOURCE > #include <stdio.h> > #include <fenv.h> > > int main() > { > printf("%d\n", feenableexcept(FE_INEXACT)); > > double data = 114.514; > long control; > asm("cfc1\t%1,$f26\n\t" > "ceil.l.d\t%0,%0\n\t" > "cvt.d.l\t%0,%0\n\t" > "ctc1\t%1,$f26": "+f"(data), "=r"(control)); > printf("%.15f\n", data); > return 0; > } > > On i386 the fnstenv instruction also masks out all the FP exceptions so > this is not a problem. See commit 26b0bf96000a. I can use "ctc1 $0, $28" to disable all float point exception to ensure no FP exceptions occur at here. But it will introduce additional consumption.
在 2023/12/25 20:36, YunQiang Su 写道: > > Junxian Zhu <zhujunxian@oss.cipunited.com> 于 2023年12月25日周一 > 18:38写道: > > From: Junxian Zhu <zhujunxian@oss.cipunited.com> > > Use hardware floating-point rounding instructions to implement > roundeven, trunc, ceil and floor. > > * sysdeps/mips/mips32/Implies: Add source path. > * sysdeps/mips/mips64/Implies: Likewise. > * sysdeps/mips/fpu/Makefile: Newfile. > * sysdeps/mips/fpu/s_ceil.c: Likewise. > * sysdeps/mips/fpu/s_ceil_fpu.S: Likewise. > * sysdeps/mips/fpu/s_ceilf.c: Likewise. > * sysdeps/mips/fpu/s_ceilf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_floor.c: Likewise. > * sysdeps/mips/fpu/s_floor_fpu.S: Likewise. > * sysdeps/mips/fpu/s_floorf.c: Likewise. > * sysdeps/mips/fpu/s_floorf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_roundeven.c: Likewise. > * sysdeps/mips/fpu/s_roundeven_fpu.S: Likewise. > * sysdeps/mips/fpu/s_roundevenf.c: Likewise. > * sysdeps/mips/fpu/s_roundevenf_fpu.S: Likewise. > * sysdeps/mips/fpu/s_trunc.c: Likewise. > * sysdeps/mips/fpu/s_trunc_fpu.S: Likewise. > * sysdeps/mips/fpu/s_truncf.c: Likewise. > * sysdeps/mips/fpu/s_truncf_fpu.S: Likewise. > > Signed-off-by: Rong Zhang <rongrong@oss.cipunited.com> > Signed-off-by: Junxian Zhu <zhujunxian@oss.cipunited.com> > --- > sysdeps/mips/fpu/Makefile | 12 ++++ > sysdeps/mips/fpu/s_ceil.c | 30 ++++++++++ > sysdeps/mips/fpu/s_ceil_fpu.S | 90 > +++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_ceilf.c | 30 ++++++++++ > sysdeps/mips/fpu/s_ceilf_fpu.S | 82 ++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_floor.c | 24 ++++++++ > sysdeps/mips/fpu/s_floor_fpu.S | 88 ++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_floorf.c | 24 ++++++++ > sysdeps/mips/fpu/s_floorf_fpu.S | 80 +++++++++++++++++++++++++ > sysdeps/mips/fpu/s_roundeven.c | 24 ++++++++ > sysdeps/mips/fpu/s_roundeven_fpu.S | 87 ++++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_roundevenf.c | 24 ++++++++ > sysdeps/mips/fpu/s_roundevenf_fpu.S | 79 +++++++++++++++++++++++++ > sysdeps/mips/fpu/s_trunc.c | 24 ++++++++ > sysdeps/mips/fpu/s_trunc_fpu.S | 84 +++++++++++++++++++++++++++ > sysdeps/mips/fpu/s_truncf.c | 24 ++++++++ > sysdeps/mips/fpu/s_truncf_fpu.S | 76 ++++++++++++++++++++++++ > sysdeps/mips/mips32/Implies | 1 + > sysdeps/mips/mips64/Implies | 1 + > 19 files changed, 884 insertions(+) > create mode 100644 sysdeps/mips/fpu/Makefile > create mode 100644 sysdeps/mips/fpu/s_ceil.c > create mode 100644 sysdeps/mips/fpu/s_ceil_fpu.S > create mode 100644 sysdeps/mips/fpu/s_ceilf.c > create mode 100644 sysdeps/mips/fpu/s_ceilf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_floor.c > create mode 100644 sysdeps/mips/fpu/s_floor_fpu.S > create mode 100644 sysdeps/mips/fpu/s_floorf.c > create mode 100644 sysdeps/mips/fpu/s_floorf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_roundeven.c > create mode 100644 sysdeps/mips/fpu/s_roundeven_fpu.S > create mode 100644 sysdeps/mips/fpu/s_roundevenf.c > create mode 100644 sysdeps/mips/fpu/s_roundevenf_fpu.S > create mode 100644 sysdeps/mips/fpu/s_trunc.c > create mode 100644 sysdeps/mips/fpu/s_trunc_fpu.S > create mode 100644 sysdeps/mips/fpu/s_truncf.c > create mode 100644 sysdeps/mips/fpu/s_truncf_fpu.S > > diff --git a/sysdeps/mips/fpu/Makefile b/sysdeps/mips/fpu/Makefile > new file mode 100644 > index 0000000000..ad537d6bf1 > --- /dev/null > +++ b/sysdeps/mips/fpu/Makefile > @@ -0,0 +1,12 @@ > +ifeq ($(subdir),math) > +sysdep_routines += s_floor_fpu s_floorf_fpu \ > + s_ceil_fpu s_ceilf_fpu \ > + s_trunc_fpu s_truncf_fpu \ > + s_roundeven_fpu s_roundevenf_fpu > + > +libm-sysdep_routines += s_floor_fpu s_floorf_fpu \ > + s_ceil_fpu s_ceilf_fpu \ > + s_trunc_fpu s_truncf_fpu \ > + s_roundeven_fpu s_roundevenf_fpu > + > +endif > diff --git a/sysdeps/mips/fpu/s_ceil.c b/sysdeps/mips/fpu/s_ceil.c > new file mode 100644 > index 0000000000..91a90a70c5 > --- /dev/null > +++ b/sysdeps/mips/fpu/s_ceil.c > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2023 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 > + <https://www.gnu.org/licenses/>. */ > + > +/* > + * ceil(x) > + * Return x rounded toward -inf to integral value > + * Method: > + * Bit twiddling. > + */ > + > +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) > \ > + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > + > > > __mips_fpr == 64 > this condition should not be here. > it means fp64. > In fact your code should also support fp32 and fpxx. > The MIPS instruction documentation has specifies restrictions for the ceil, round, floor and trunc. "The result of this instruction is UNPREDICTABLE if the processor is executing in the FR=0 32-bit FPU register model; it is predictable if executing on a 64-bit FPU in the FR=1 mode, but not with FR=0, and not on a 32-bit FPU." And fp64 ABI is the only configuration that restricts FPU work in FR=1 mode.
On Tue, 2024-01-02 at 17:43 +0800, Junxian Zhu wrote: > 在 2023/12/26 16:29, Xi Ruoyao 写道: > > On Tue, 2023-12-26 at 10:37 +0800, Junxian Zhu wrote: > > > 在 2023/12/25 18:51, Xi Ruoyao 写道: > > > > On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: > > > > > > > > /* snip */ > > > > > > > > > +/* > > > > > + * ceil(x) > > > > > + * Return x rounded toward -inf to integral value > > > > > + * Method: > > > > > + * Bit twiddling. > > > > > + */ > > > > > + > > > > > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > > > > > +#include <sys/regdef.h> > > > > > +#include <sysdep.h> > > > > > +#include <libm-alias-double.h> > > > > > + > > > > > +ENTRY(__ceil) > > > > > + .set push > > > > > + .set noreorder > > > > > + .set noat > > > > > +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp > > > > > +#if __mips == 64 > > > > > + dmfc1 a0, $f12 # assign int64 > > > > > +#else > > > > > + mfhc1 a0, $f12 # assign int64 > > > > > +#endif > > > > > + cfc1 t0, $f26 > > > > > + ceil.l.d $f0, $f12 > > > > No, C23 does not allow this function to raise an INEXACT exception, but > > > > ceil.l.d will do so. > > > > > > > > Such optimizations should be performed in GCC which can be controlled by > > > > the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not > > > > in Glibc where we cannot know if the programmer wants to deviate from > > > > C23. > > > The cfc1 instruction will backup float point exception status before > > > running ceil.l.d, and the following ctc1 will restore float point > > > exception status to avoid INEXACT exception raised by ceil.l.d. It's the > > > same way like what have been done in s_ceil.S for i386. > > Still incorrect because when the Enable field of FCSR contains INEXACT a > > SIGFPE will be immediately delivered and there is no way to recover. A > > demonstration: > > > > #define _GNU_SOURCE > > #include <stdio.h> > > #include <fenv.h> > > > > int main() > > { > > printf("%d\n", feenableexcept(FE_INEXACT)); > > > > double data = 114.514; > > long control; > > asm("cfc1\t%1,$f26\n\t" > > "ceil.l.d\t%0,%0\n\t" > > "cvt.d.l\t%0,%0\n\t" > > "ctc1\t%1,$f26": "+f"(data), "=r"(control)); > > printf("%.15f\n", data); > > return 0; > > } > > > > On i386 the fnstenv instruction also masks out all the FP exceptions so > > this is not a problem. See commit 26b0bf96000a. > > I can use "ctc1 $0, $28" to disable all float point exception to ensure > no FP exceptions occur at here. But it will introduce additional > consumption. And then it will likely be even slower than the generic implementation like Adhemerval already tested on the cfarm machine. Frankly I'm even unsure if your (incorrect) implementation is really faster than the generic implementation: if the uarch just handles all ctc1 instructions equally (i.e. always stalling the FP unit or even the entire CPU for a dozen of cycles) it would be already slower. Have you benchmarked this on real hardware? Note that benchmarking on things like QEMU can be completely misleading.
在 2023/12/27 6:50, Xi Ruoyao 写道: > On Wed, 2023-12-27 at 05:50 +0800, Xi Ruoyao wrote: >> On Tue, 2023-12-26 at 17:12 -0300, Adhemerval Zanella Netto wrote: >>> Also, I see no point in implementing this optimizations with assembly where >>> a C implementation would be way simpler and generate similar code. Similar >>> to what I did for powerpc with sysdeps/powerpc/fpu/round_to_integer.h, I >>> implemented a similar approach for MIPS [1]. The resulting code should be >>> similar to the assembly implementation, taking in consideration the correct >>> fix to save/restore floating-point exceptions. I did see no math regression >>> on cfarm23 with a glibc built with -mabi=64 -mips64r2. >> Is there a micro-benchmark result on the cfarm machine? AFAIK the FCSR >> setting instruction may be much more slower than normal instructions, so >> I'm not sure if this is really a win. > Add Jiaxun who knows MIPS much better than me. After disscussion with Jiaxun, we guess that the consuming of switching mode in FCSR is the cause of FPU implements slower than generic implements. If we don't change or switching mode in FCSR, the FPU implements will be faster than generic implements. Tested on Imagination Ci40 (MIPS interAptiv (multi) V2.0 FPU V0.0)and loogson 3A2000. So it's enough to use generic C implements for rounding on MIPS.......
在 2023/12/25 18:51, Xi Ruoyao 写道: > On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: > > /* snip */ > >> +/* >> + * ceil(x) >> + * Return x rounded toward -inf to integral value >> + * Method: >> + * Bit twiddling. >> + */ >> + >> +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) >> +#include <sys/regdef.h> >> +#include <sysdep.h> >> +#include <libm-alias-double.h> >> + >> +ENTRY(__ceil) >> + .set push >> + .set noreorder >> + .set noat >> +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp >> +#if __mips == 64 >> + dmfc1 a0, $f12 # assign int64 >> +#else >> + mfhc1 a0, $f12 # assign int64 >> +#endif >> + cfc1 t0, $f26 >> + ceil.l.d $f0, $f12 > No, C23 does not allow this function to raise an INEXACT exception, but > ceil.l.d will do so. > > Such optimizations should be performed in GCC which can be controlled by > the programmer with -std=c23 and/or -f[no-]fp-int-builtin-inexact, not > in Glibc where we cannot know if the programmer wants to deviate from > C23. Recently, I'm still trying to do some optimization for MIPS. I want to know if I use rounding instructions on MIPS, like |round.l.d|, in functions with parameters input in FPR and results in GPR, like |llrint|or |lrint|, will we still face the INEXACT exception and potentially violate C23?
On Thu, 2024-01-25 at 21:58 +0800, Junxian Zhu wrote: > Recently, I'm still trying to do some optimization for MIPS. I want to > know if I use rounding instructions on MIPS, like |round.l.d|, in > functions with parameters input in FPR and results in GPR, like > > llrint|or |lrint|, will we still face the INEXACT exception and > potentially violate C23? C23 explicitly says llrint and lrint *raises* FE_INEXACT exception when they raise no other floating-point exception and the result differs from the argument. But you should still do the optimization in GCC, then define USE_LRINT_BUILTIN etc. in Glibc if GCC is recent enough to support it. By doing this in the compiler, users can avoid an overhead to do a function call (esp. on MIPS with all the "abicall" stuff the overhead is very large).
On Wed, 2024-01-31 at 11:28 +0800, Junxian Zhu wrote: > 在 2023/12/26 16:29, Xi Ruoyao 写道: > > On Tue, 2023-12-26 at 10:37 +0800, Junxian Zhu wrote: > > > 在 2023/12/25 18:51, Xi Ruoyao 写道: > > > > On Mon, 2023-12-25 at 18:35 +0800, Junxian Zhu wrote: > > > > > > > > /* snip */ > > > > > > > > > +/* > > > > > + * ceil(x) > > > > > + * Return x rounded toward -inf to integral value > > > > > + * Method: > > > > > + * Bit twiddling. > > > > > + */ > > > > > + > > > > > +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && > > > > > ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) > > > > > +#include <sys/regdef.h> > > > > > +#include <sysdep.h> > > > > > +#include <libm-alias-double.h> > > > > > + > > > > > +ENTRY(__ceil) > > > > > + .set push > > > > > + .set noreorder > > > > > + .set noat > > > > > +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, > > > > > a2=sign, a3=exp > > > > > +#if __mips == 64 > > > > > + dmfc1 a0, $f12 # assign int64 > > > > > +#else > > > > > + mfhc1 a0, $f12 # assign int64 > > > > > +#endif > > > > > + cfc1 t0, $f26 > > > > > + ceil.l.d $f0, $f12 > > > > No, C23 does not allow this function to raise an INEXACT > > > > exception, but > > > > ceil.l.d will do so. > > > > > > > > Such optimizations should be performed in GCC which can be > > > > controlled by > > > > the programmer with -std=c23 and/or -f[no-]fp-int-builtin- > > > > inexact, not > > > > in Glibc where we cannot know if the programmer wants to deviate > > > > from > > > > C23. > > > The cfc1 instruction will backup float point exception status > > > before > > > running ceil.l.d, and the following ctc1 will restore float point > > > exception status to avoid INEXACT exception raised by ceil.l.d. > > > It's the > > > same way like what have been done in s_ceil.S for i386. > > Still incorrect because when the Enable field of FCSR contains > > INEXACT a > > SIGFPE will be immediately delivered and there is no way to > > recover. A > > demonstration: > > > > #define _GNU_SOURCE > > #include <stdio.h> > > #include <fenv.h> > > > > int main() > > { > > printf("%d\n", feenableexcept(FE_INEXACT)); > > > > double data = 114.514; > > long control; > > asm("cfc1\t%1,$f26\n\t" > > "ceil.l.d\t%0,%0\n\t" > > "cvt.d.l\t%0,%0\n\t" > > "ctc1\t%1,$f26": "+f"(data), "=r"(control)); > > printf("%.15f\n", data); > > return 0; > > } > > > > On i386 the fnstenv instruction also masks out all the FP exceptions > > so > > this is not a problem. See commit 26b0bf96000a. > > I made some similar code to test and found that sqrt.fmt on MIPS will > raise INEXACT exception too. > > So should we mask all the FP exceptions while compiling MIPS > SQRT{F}_BUILTIN in GCC ? (for C23) Why? volatile double x = 2; sqrt(x); should definitely raise an INEXACT exception. Unless explicitly stated otherwise, all operations producing a result different than the "infinite precision operation" should do it. For the conversion operations they are just "explicitly stated otherwise." But if sqrt.fmt is raising it for volatile double x = 4; sqrt(x); it's obviously wrong, and I'd say such an exception is nonsense even regardless of the standard so we should just not use this instruction. Something not so obvious is: the standard explicitly says volatile double x = __builtin_inf(); sqrt(x); should **not** raise an INEXACT exception. So if you are raising INEXACT for this you should only use sqrt.fmt when you can prove the operand is finite (for example when -ffinite-math-only, or using some information from the VRP pass).
diff --git a/sysdeps/mips/fpu/Makefile b/sysdeps/mips/fpu/Makefile new file mode 100644 index 0000000000..ad537d6bf1 --- /dev/null +++ b/sysdeps/mips/fpu/Makefile @@ -0,0 +1,12 @@ +ifeq ($(subdir),math) +sysdep_routines += s_floor_fpu s_floorf_fpu \ + s_ceil_fpu s_ceilf_fpu \ + s_trunc_fpu s_truncf_fpu \ + s_roundeven_fpu s_roundevenf_fpu + +libm-sysdep_routines += s_floor_fpu s_floorf_fpu \ + s_ceil_fpu s_ceilf_fpu \ + s_trunc_fpu s_truncf_fpu \ + s_roundeven_fpu s_roundevenf_fpu + +endif diff --git a/sysdeps/mips/fpu/s_ceil.c b/sysdeps/mips/fpu/s_ceil.c new file mode 100644 index 0000000000..91a90a70c5 --- /dev/null +++ b/sysdeps/mips/fpu/s_ceil.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/dbl-64/s_ceil.c> + +#endif diff --git a/sysdeps/mips/fpu/s_ceil_fpu.S b/sysdeps/mips/fpu/s_ceil_fpu.S new file mode 100644 index 0000000000..13d4f85ad3 --- /dev/null +++ b/sysdeps/mips/fpu/s_ceil_fpu.S @@ -0,0 +1,90 @@ +/* Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-double.h> + +ENTRY(__ceil) + .set push + .set noreorder + .set noat +# $f0=ret, $f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp +#if __mips == 64 + dmfc1 a0, $f12 # assign int64 +#else + mfhc1 a0, $f12 # assign int64 +#endif + cfc1 t0, $f26 + ceil.l.d $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 52, 11 # assign exp +#else + dsrl a3, a0, 52 + andi a3, a3, 0x7ff +#endif +#else + ext a3, a0, 20, 11 # assign exp +#endif + sltiu AT, a3, 1023 + bnez AT, SMALL # exp < 1023 + ctc1 t0, $f26 + sltiu AT, a3, 1023+54 + beqz AT, BIG # exp >= 1023+54 + li AT, 0x7ff + + jr ra + cvt.d.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac + nop +NAN_INF: + jr ra + add.d $f0, $f12, $f12 # return double + double +SMALL: +#if __mips == 64 + dsrl a2, a0, 63 +#else + srl a2, a0, 31 +#endif + beqz a2, SMALL_POSITIVE # sign == 0 + nop +SMALL_NEGATIVE: # return -0.0 + jr ra + neg.d $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.d.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.d $f0, $f12 + .set pop + +END (__ceil) +libm_alias_double (__ceil, ceil) + +#endif + diff --git a/sysdeps/mips/fpu/s_ceilf.c b/sysdeps/mips/fpu/s_ceilf.c new file mode 100644 index 0000000000..a7f81c7539 --- /dev/null +++ b/sysdeps/mips/fpu/s_ceilf.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/flt-32/s_ceilf.c> + +#endif diff --git a/sysdeps/mips/fpu/s_ceilf_fpu.S b/sysdeps/mips/fpu/s_ceilf_fpu.S new file mode 100644 index 0000000000..7952894f73 --- /dev/null +++ b/sysdeps/mips/fpu/s_ceilf_fpu.S @@ -0,0 +1,82 @@ +/* Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-float.h> + +ENTRY(__ceilf) + .set push + .set noreorder + .set noat +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp + mfc1 a0, $f12 # assign int32 + cfc1 t0, $f26 + ceil.l.s $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 23, 8 # assign exp +#else + dsrl a3, a0, 23 + andi a3, a3, 0x1ff +#endif +#else + ext a3, a0, 23, 8 # assign exp +#endif + sltiu AT, a3, 127 + bnez AT, SMALL # exp < 127 + ctc1 t0, $f26 + sltiu AT, a3, 127+25 + beqz AT, BIG # exp >= 127+25 + li AT, 0xff + + jr ra + cvt.s.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac + nop +NAN_INF: + jr ra + add.s $f0, $f12, $f12 # return double + double +SMALL: + srl a2, a0, 31 + beqz a2, SMALL_POSITIVE # sign == 0 + nop +SMALL_NEGATIVE: # return -0.0 + jr ra + neg.s $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.s.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.s $f0, $f12 + .set pop + +END (__ceilf) +libm_alias_float (__ceil, ceil) + +#endif + diff --git a/sysdeps/mips/fpu/s_floor.c b/sysdeps/mips/fpu/s_floor.c new file mode 100644 index 0000000000..4b43dc9ad9 --- /dev/null +++ b/sysdeps/mips/fpu/s_floor.c @@ -0,0 +1,24 @@ +/* Round double to integer away from zero. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/dbl-64/s_floor.c> + +#endif diff --git a/sysdeps/mips/fpu/s_floor_fpu.S b/sysdeps/mips/fpu/s_floor_fpu.S new file mode 100644 index 0000000000..fda661fd3a --- /dev/null +++ b/sysdeps/mips/fpu/s_floor_fpu.S @@ -0,0 +1,88 @@ +/* Round double to integer away from zero. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-double.h> + +ENTRY(__floor) + .set push + .set noreorder + .set noat +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp +#if __mips == 64 + dmfc1 a0, $f12 # assign int64 +#else + mfhc1 a0, $f12 # assign int64 +#endif + cfc1 t0, $f26 + floor.l.d $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 52, 11 # assign exp +#else + dsrl a3, a0, 52 + andi a3, a3, 0x7ff +#endif +#else + ext a3, a0, 20, 11 # assign exp +#endif + sltiu AT, a3, 1023 + bnez AT, SMALL # exp < 1023 + ctc1 t0, $f26 + sltiu AT, a3, 1023+54 + beqz AT, BIG # exp >= 1023+54 + li AT, 0x7ff + + jr ra + cvt.d.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac + nop +NAN_INF: + jr ra + add.d $f0, $f12, $f12 # return double + double +SMALL: +#if __mips == 64 + dsrl a2, a0, 63 +#else + srl a2, a0, 31 +#endif + beqz a2, SMALL_POSITIVE # sign == 0 + li AT, 0xbff # used by SMALL_NEGATIVE +SMALL_NEGATIVE: + mfhc1 t1, $f0 + bnez t1, SMALL_POSITIVE # sign == 0 + nop + + jr ra + neg.d $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.d.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.d $f0, $f12 + .set pop + +END (__floor) +libm_alias_double (__floor, floor) + +#endif + diff --git a/sysdeps/mips/fpu/s_floorf.c b/sysdeps/mips/fpu/s_floorf.c new file mode 100644 index 0000000000..30cfda7820 --- /dev/null +++ b/sysdeps/mips/fpu/s_floorf.c @@ -0,0 +1,24 @@ +/* Round double to integer away from zero. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/flt-32/s_floorf.c> + +#endif diff --git a/sysdeps/mips/fpu/s_floorf_fpu.S b/sysdeps/mips/fpu/s_floorf_fpu.S new file mode 100644 index 0000000000..8edd234dbc --- /dev/null +++ b/sysdeps/mips/fpu/s_floorf_fpu.S @@ -0,0 +1,80 @@ +/* Round double to integer away from zero. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-float.h> + +ENTRY(__floorf) + .set push + .set noreorder + .set noat +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp + mfc1 a0, $f12 # assign int32 + cfc1 t0, $f26 + floor.l.s $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 23, 8 # assign exp +#else + dsrl a3, a0, 23 + andi a3, a3, 0x1ff +#endif +#else + ext a3, a0, 23, 8 # assign exp +#endif + sltiu AT, a3, 127 + bnez AT, SMALL # exp < 127 + ctc1 t0, $f26 + sltiu AT, a3, 127+25 + beqz AT, BIG # exp >= 127+25 + li AT, 0xff + + jr ra + cvt.s.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac + nop +NAN_INF: + jr ra + add.s $f0, $f12, $f12 # return double + double +SMALL: + srl a2, a0, 31 + beqz a2, SMALL_POSITIVE # sign == 0 + li AT, 0xbff # used by SMALL_NEGATIVE +SMALL_NEGATIVE: + mfhc1 t1, $f0 + bnez t1, SMALL_POSITIVE # sign == 0 + nop + + jr ra + neg.s $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.s.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.s $f0, $f12 + .set pop + +END (__floorf) +libm_alias_float (__floor, floor) + +#endif + diff --git a/sysdeps/mips/fpu/s_roundeven.c b/sysdeps/mips/fpu/s_roundeven.c new file mode 100644 index 0000000000..dace85a70b --- /dev/null +++ b/sysdeps/mips/fpu/s_roundeven.c @@ -0,0 +1,24 @@ +/* Round to nearest integer value, rounding halfway cases to even. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/dbl-64/s_roundeven.c> + +#endif diff --git a/sysdeps/mips/fpu/s_roundeven_fpu.S b/sysdeps/mips/fpu/s_roundeven_fpu.S new file mode 100644 index 0000000000..aef6434886 --- /dev/null +++ b/sysdeps/mips/fpu/s_roundeven_fpu.S @@ -0,0 +1,87 @@ +/* Round to nearest integer value, rounding halfway cases to even. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-double.h> + +ENTRY(__roundeven) + .set push + .set noreorder + .set noat +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp +#if __mips == 64 + dmfc1 a0, $f12 # assign int64 +#else + mfhc1 a0, $f12 # assign int64 +#endif + cfc1 t0, $f26 + round.l.d $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 52, 11 # assign exp +#else + dsrl a3, a0, 52 + andi a3, a3, 0x7ff +#endif +#else + ext a3, a0, 20, 11 # assign exp +#endif + sltiu AT, a3, 1023 + bnez AT, SMALL # exp < 1023 + ctc1 t0, $f26 + sltiu AT, a3, 1023+54 + beqz AT, BIG # exp >= 1023+54 + li AT, 0x7ff + + jr ra + cvt.d.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac + nop +NAN_INF: + jr ra + add.d $f0, $f12, $f12 # return double + double +SMALL: +#if __mips == 64 + dsrl a2, a0, 63 +#else + srl a2, a0, 31 +#endif + beqz a2, SMALL_POSITIVE # sign == 0 + nop +SMALL_NEGATIVE: + mfhc1 t1, $f0 + bnez t1, SMALL_POSITIVE # sign == 0 + nop + + jr ra + neg.d $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.d.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.d $f0, $f12 + .set pop + +END (__roundeven) +libm_alias_double (__roundeven, roundeven) + +#endif diff --git a/sysdeps/mips/fpu/s_roundevenf.c b/sysdeps/mips/fpu/s_roundevenf.c new file mode 100644 index 0000000000..5bb35901db --- /dev/null +++ b/sysdeps/mips/fpu/s_roundevenf.c @@ -0,0 +1,24 @@ +/* Round to nearest integer value, rounding halfway cases to even. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/flt-32/s_roundevenf.c> + +#endif diff --git a/sysdeps/mips/fpu/s_roundevenf_fpu.S b/sysdeps/mips/fpu/s_roundevenf_fpu.S new file mode 100644 index 0000000000..e946e50d8f --- /dev/null +++ b/sysdeps/mips/fpu/s_roundevenf_fpu.S @@ -0,0 +1,79 @@ +/* Round to nearest integer value, rounding halfway cases to even. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-float.h> + +ENTRY(__roundevenf) + .set push + .set noreorder + .set noat +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp + mfc1 a0, $f12 # assign int32 + cfc1 t0, $f26 + round.l.s $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 23, 8 # assign exp +#else + dsrl a3, a0, 23 + andi a3, a3, 0x1ff +#endif +#else + ext a3, a0, 23, 8 # assign exp +#endif + sltiu AT, a3, 127 + bnez AT, SMALL # exp < 127 + ctc1 t0, $f26 + sltiu AT, a3, 127+25 + beqz AT, BIG # exp >= 127+25 + li AT, 0xff + + jr ra + cvt.s.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac + nop +NAN_INF: + jr ra + add.s $f0, $f12, $f12 # return double + double +SMALL: + srl a2, a0, 31 + beqz a2, SMALL_POSITIVE # sign == 0 + nop +SMALL_NEGATIVE: + mfhc1 t1, $f0 + bnez t1, SMALL_POSITIVE # sign == 0 + nop + + jr ra + neg.s $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.s.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.s $f0, $f12 + .set pop + +END (__roundevenf) +libm_alias_float (__roundeven, roundeven) + +#endif diff --git a/sysdeps/mips/fpu/s_trunc.c b/sysdeps/mips/fpu/s_trunc.c new file mode 100644 index 0000000000..3865026c70 --- /dev/null +++ b/sysdeps/mips/fpu/s_trunc.c @@ -0,0 +1,24 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/dbl-64/s_trunc.c> + +#endif diff --git a/sysdeps/mips/fpu/s_trunc_fpu.S b/sysdeps/mips/fpu/s_trunc_fpu.S new file mode 100644 index 0000000000..3a7947507f --- /dev/null +++ b/sysdeps/mips/fpu/s_trunc_fpu.S @@ -0,0 +1,84 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-double.h> + +ENTRY(__trunc) + .set push + .set noreorder + .set noat +# f0=ret, f12=double, a0=int64/int32_h, a1=int32_l, a2=sign, a3=exp +#if __mips == 64 + dmfc1 a0, $f12 # assign int64 +#else + mfhc1 a0, $f12 # assign int64 +#endif + cfc1 t0, $f26 + trunc.l.d $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 52, 11 # assign exp +#else + dsrl a3, a0, 52 + andi a3, a3, 0x7ff +#endif +#else + ext a3, a0, 20, 11 # assign exp +#endif + sltiu AT, a3, 1023 + bnez AT, SMALL # exp < 1023 + ctc1 t0, $f26 + sltiu AT, a3, 1023+54 + beqz AT, BIG # exp >= 1023+54 + li AT, 0x7ff + + jr ra + cvt.d.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0x7ff, no frac + nop +NAN_INF: + jr ra + add.d $f0, $f12, $f12 # return double + double +SMALL: +#if __mips == 64 + dsrl a2, a0, 63 +#else + srl a2, a0, 31 +#endif + beqz a2, SMALL_POSITIVE # sign == 0 + nop +SMALL_NEGATIVE: # return -0.0 + jr ra + neg.d $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.d.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.d $f0, $f12 + .set pop + +END (__trunc) +libm_alias_double (__trunc, trunc) + +#endif + diff --git a/sysdeps/mips/fpu/s_truncf.c b/sysdeps/mips/fpu/s_truncf.c new file mode 100644 index 0000000000..59ef17bf74 --- /dev/null +++ b/sysdeps/mips/fpu/s_truncf.c @@ -0,0 +1,24 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if !((__mips_fpr == 64) && (__mips_hard_float == 1) \ + && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) + +# include <sysdeps/ieee754/flt-32/s_truncf.c> + +#endif diff --git a/sysdeps/mips/fpu/s_truncf_fpu.S b/sysdeps/mips/fpu/s_truncf_fpu.S new file mode 100644 index 0000000000..1878d88e3c --- /dev/null +++ b/sysdeps/mips/fpu/s_truncf_fpu.S @@ -0,0 +1,76 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 2023 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 + <https://www.gnu.org/licenses/>. */ + +#if ((__mips_fpr == 64) && (__mips_hard_float == 1) && ((__mips == 32 && __mips_isa_rev > 1) || __mips == 64)) +#include <sys/regdef.h> +#include <sysdep.h> +#include <libm-alias-float.h> + +ENTRY(__truncf) + .set push + .set noreorder + .set noat +# f0=ret, f12=float, a0=int32, a2=sign, a3=exp + mfc1 a0, $f12 # assign int32 + cfc1 t0, $f26 + trunc.l.s $f0, $f12 +#if __mips == 64 +#if __mips_isa_rev > 1 + dext a3, a0, 23, 8 # assign exp +#else + dsrl a3, a0, 23 + andi a3, a3, 0x1ff +#endif +#else + ext a3, a0, 23, 8 # assign exp +#endif + sltiu AT, a3, 127 + bnez AT, SMALL # exp < 127 + ctc1 t0, $f26 + sltiu AT, a3, 127+25 + beqz AT, BIG # exp >= 127+25 + li AT, 0xff + + jr ra + cvt.s.l $f0, $f0 +BIG: + bne AT, a3, RETURN_AS_IS # exp != 0xff, no frac + nop +NAN_INF: + jr ra + add.s $f0, $f12, $f12 # return double + double +SMALL: + srl a2, a0, 31 + beqz a2, SMALL_POSITIVE # sign == 0 + nop +SMALL_NEGATIVE: # return -0.0 + jr ra + neg.s $f0, $f0 +SMALL_POSITIVE: + jr ra + cvt.s.l $f0, $f0 +RETURN_AS_IS: + jr ra + mov.s $f0, $f12 + .set pop + +END (__truncf) +libm_alias_float (__trunc, trunc) + +#endif + diff --git a/sysdeps/mips/mips32/Implies b/sysdeps/mips/mips32/Implies index 6473f2517c..71b3678c6c 100644 --- a/sysdeps/mips/mips32/Implies +++ b/sysdeps/mips/mips32/Implies @@ -1,3 +1,4 @@ +mips/fpu mips/ieee754 mips wordsize-32 diff --git a/sysdeps/mips/mips64/Implies b/sysdeps/mips/mips64/Implies index 826ff1541f..8885ebd564 100644 --- a/sysdeps/mips/mips64/Implies +++ b/sysdeps/mips/mips64/Implies @@ -1,4 +1,5 @@ # MIPS uses IEEE 754 floating point. +mips/fpu mips/ieee754 ieee754/flt-32 ieee754/dbl-64