x86_64: roundeven with fpu and sse4.1 support

Message ID 20191214161138.4134889-1-ibmibmibm.tw@gmail.com
State Superseded
Headers

Commit Message

謝昇達(Shen-Ta Hsieh) Dec. 14, 2019, 4:11 p.m. UTC
  This patch adds support for the various other hardware floating point
configurations that i386 and x86_64 supports.
---
 include/math.h                                |  1 -
 sysdeps/i386/fpu/s_roundeven.S                | 38 +++++++++++++++
 sysdeps/i386/fpu/s_roundevenf.S               | 38 +++++++++++++++
 sysdeps/i386/fpu/s_roundevenl.S               | 41 ++++++++++++++++
 sysdeps/ieee754/dbl-64/s_roundeven.c          |  3 +-
 sysdeps/x86_64/fpu/multiarch/Makefile         |  5 +-
 sysdeps/x86_64/fpu/multiarch/s_roundeven-c.c  |  2 +
 .../x86_64/fpu/multiarch/s_roundeven-sse4_1.S | 26 ++++++++++
 sysdeps/x86_64/fpu/multiarch/s_roundeven.c    | 31 ++++++++++++
 sysdeps/x86_64/fpu/multiarch/s_roundevenf-c.c |  3 ++
 .../fpu/multiarch/s_roundevenf-sse4_1.S       | 26 ++++++++++
 sysdeps/x86_64/fpu/multiarch/s_roundevenf.c   | 31 ++++++++++++
 sysdeps/x86_64/fpu/s_roundevenl.S             | 47 +++++++++++++++++++
 13 files changed, 288 insertions(+), 4 deletions(-)
 create mode 100644 sysdeps/i386/fpu/s_roundeven.S
 create mode 100644 sysdeps/i386/fpu/s_roundevenf.S
 create mode 100644 sysdeps/i386/fpu/s_roundevenl.S
 create mode 100644 sysdeps/x86_64/fpu/multiarch/s_roundeven-c.c
 create mode 100644 sysdeps/x86_64/fpu/multiarch/s_roundeven-sse4_1.S
 create mode 100644 sysdeps/x86_64/fpu/multiarch/s_roundeven.c
 create mode 100644 sysdeps/x86_64/fpu/multiarch/s_roundevenf-c.c
 create mode 100644 sysdeps/x86_64/fpu/multiarch/s_roundevenf-sse4_1.S
 create mode 100644 sysdeps/x86_64/fpu/multiarch/s_roundevenf.c
 create mode 100644 sysdeps/x86_64/fpu/s_roundevenl.S
  

Patch

diff --git a/include/math.h b/include/math.h
index a274f2bdfd..2638323a1a 100644
--- a/include/math.h
+++ b/include/math.h
@@ -38,7 +38,6 @@  libm_hidden_proto (__issignaling)
 libm_hidden_proto (__issignalingf)
 libm_hidden_proto (__exp)
 libm_hidden_proto (__expf)
-libm_hidden_proto (__roundeven)
 
 # ifndef __NO_LONG_DOUBLE_MATH
 libm_hidden_proto (__fpclassifyl)
diff --git a/sysdeps/i386/fpu/s_roundeven.S b/sysdeps/i386/fpu/s_roundeven.S
new file mode 100644
index 0000000000..1cf78cf952
--- /dev/null
+++ b/sysdeps/i386/fpu/s_roundeven.S
@@ -0,0 +1,38 @@ 
+/* Round to nearest integer value, rounding halfway cases to even.
+   double version.
+   Copyright (C) 2019 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/>.  */
+
+#include <machine/asm.h>
+#include <libm-alias-double.h>
+
+ENTRY(__roundeven)
+	fldl	4(%esp)
+	subl	$32, %esp
+	cfi_adjust_cfa_offset (32)
+	fnstenv	4(%esp)
+	movl	$0xf3ff, %edx
+	andl	4(%esp), %edx
+	movl	%edx, (%esp)
+	fldcw	(%esp)
+	frndint
+	fldenv	4(%esp)
+	addl	$32, %esp
+	cfi_adjust_cfa_offset (-32)
+	ret
+END(__roundeven)
+libm_alias_double (__roundeven, roundeven)
diff --git a/sysdeps/i386/fpu/s_roundevenf.S b/sysdeps/i386/fpu/s_roundevenf.S
new file mode 100644
index 0000000000..eaf092e325
--- /dev/null
+++ b/sysdeps/i386/fpu/s_roundevenf.S
@@ -0,0 +1,38 @@ 
+/* Round to nearest integer value, rounding halfway cases to even.
+   float version.
+   Copyright (C) 2019 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/>.  */
+
+#include <machine/asm.h>
+#include <libm-alias-float.h>
+
+ENTRY(__roundevenf)
+	flds	4(%esp)
+	subl	$32, %esp
+	cfi_adjust_cfa_offset (32)
+	fnstenv	4(%esp)
+	movl	$0xf3ff, %edx
+	andl	4(%esp), %edx
+	movl	%edx, (%esp)
+	fldcw	(%esp)
+	frndint
+	fldenv	4(%esp)
+	addl	$32, %esp
+	cfi_adjust_cfa_offset (-32)
+	ret
+END(__roundevenf)
+libm_alias_float (__roundeven, roundeven)
diff --git a/sysdeps/i386/fpu/s_roundevenl.S b/sysdeps/i386/fpu/s_roundevenl.S
new file mode 100644
index 0000000000..b3fc10c1da
--- /dev/null
+++ b/sysdeps/i386/fpu/s_roundevenl.S
@@ -0,0 +1,41 @@ 
+/* Round to nearest integer value, rounding halfway cases to even.
+   long double version.
+   Copyright (C) 2019 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/>.  */
+
+#include <libm-alias-ldouble.h>
+#include <machine/asm.h>
+
+ENTRY(__roundevenl)
+	fldt	4(%esp)
+	subl	$32, %esp
+	cfi_adjust_cfa_offset (32)
+	fnstenv	4(%esp)
+	movl	$0xf3ff, %edx
+	andl	4(%esp), %edx
+	movl	%edx, (%esp)
+	fldcw	(%esp)
+	frndint
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, 8(%esp)
+	fldenv	4(%esp)
+	addl	$32, %esp
+	cfi_adjust_cfa_offset (-32)
+	ret
+END(__roundevenl)
+libm_alias_ldouble (__roundeven, roundeven)
diff --git a/sysdeps/ieee754/dbl-64/s_roundeven.c b/sysdeps/ieee754/dbl-64/s_roundeven.c
index 3a4eccb85a..11081c4952 100644
--- a/sysdeps/ieee754/dbl-64/s_roundeven.c
+++ b/sysdeps/ieee754/dbl-64/s_roundeven.c
@@ -101,5 +101,6 @@  __roundeven (double x)
   INSERT_WORDS (x, hx, lx);
   return x;
 }
-hidden_def (__roundeven)
+#ifndef __roundeven
 libm_alias_double (__roundeven, roundeven)
+#endif
diff --git a/sysdeps/x86_64/fpu/multiarch/Makefile b/sysdeps/x86_64/fpu/multiarch/Makefile
index 3836574f48..7e3a3f78cb 100644
--- a/sysdeps/x86_64/fpu/multiarch/Makefile
+++ b/sysdeps/x86_64/fpu/multiarch/Makefile
@@ -1,11 +1,12 @@ 
 ifeq ($(subdir),math)
 libm-sysdep_routines += s_floor-c s_ceil-c s_floorf-c s_ceilf-c \
 			s_rint-c s_rintf-c s_nearbyint-c s_nearbyintf-c \
-			s_trunc-c s_truncf-c
+			s_roundeven-c s_roundevenf-c s_trunc-c s_truncf-c
 
 libm-sysdep_routines += s_ceil-sse4_1 s_ceilf-sse4_1 s_floor-sse4_1 \
 			s_floorf-sse4_1 s_nearbyint-sse4_1 \
-			s_nearbyintf-sse4_1 s_rint-sse4_1 s_rintf-sse4_1 \
+			s_nearbyintf-sse4_1 s_roundeven-sse4_1 \
+			s_roundevenf-sse4_1 s_rint-sse4_1 s_rintf-sse4_1 \
 			s_trunc-sse4_1 s_truncf-sse4_1
 
 libm-sysdep_routines += e_exp-fma e_log-fma e_pow-fma s_atan-fma \
diff --git a/sysdeps/x86_64/fpu/multiarch/s_roundeven-c.c b/sysdeps/x86_64/fpu/multiarch/s_roundeven-c.c
new file mode 100644
index 0000000000..c7be43cb22
--- /dev/null
+++ b/sysdeps/x86_64/fpu/multiarch/s_roundeven-c.c
@@ -0,0 +1,2 @@ 
+#define __roundeven __roundeven_c
+#include <sysdeps/ieee754/dbl-64/s_roundeven.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_roundeven-sse4_1.S b/sysdeps/x86_64/fpu/multiarch/s_roundeven-sse4_1.S
new file mode 100644
index 0000000000..6db88a1649
--- /dev/null
+++ b/sysdeps/x86_64/fpu/multiarch/s_roundeven-sse4_1.S
@@ -0,0 +1,26 @@ 
+/* Round to nearest integer value, rounding halfway cases to even.
+   double version.
+   Copyright (C) 2019 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/>.  */
+
+#include <sysdep.h>
+
+	.section .text.sse4.1,"ax",@progbits
+ENTRY(__roundeven_sse41)
+	roundsd	$8, %xmm0, %xmm0
+	ret
+END(__roundeven_sse41)
diff --git a/sysdeps/x86_64/fpu/multiarch/s_roundeven.c b/sysdeps/x86_64/fpu/multiarch/s_roundeven.c
new file mode 100644
index 0000000000..bd777b0ca7
--- /dev/null
+++ b/sysdeps/x86_64/fpu/multiarch/s_roundeven.c
@@ -0,0 +1,31 @@ 
+/* Multiple versions of __roundeven.
+   Copyright (C) 2019 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/>.  */
+
+#include <libm-alias-double.h>
+
+#define roundeven __redirect_roundeven
+#define __roundeven __redirect___roundeven
+#include <math.h>
+#undef roundeven
+#undef __roundeven
+
+#define SYMBOL_NAME roundeven
+#include "ifunc-sse4_1.h"
+
+libc_ifunc_redirected (__redirect_roundeven, __roundeven, IFUNC_SELECTOR ());
+libm_alias_double (__roundeven, roundeven)
diff --git a/sysdeps/x86_64/fpu/multiarch/s_roundevenf-c.c b/sysdeps/x86_64/fpu/multiarch/s_roundevenf-c.c
new file mode 100644
index 0000000000..72a6e7d1fb
--- /dev/null
+++ b/sysdeps/x86_64/fpu/multiarch/s_roundevenf-c.c
@@ -0,0 +1,3 @@ 
+#undef __roundevenf
+#define __roundevenf __roundevenf_c
+#include <sysdeps/ieee754/flt-32/s_roundevenf.c>
diff --git a/sysdeps/x86_64/fpu/multiarch/s_roundevenf-sse4_1.S b/sysdeps/x86_64/fpu/multiarch/s_roundevenf-sse4_1.S
new file mode 100644
index 0000000000..74102bac0d
--- /dev/null
+++ b/sysdeps/x86_64/fpu/multiarch/s_roundevenf-sse4_1.S
@@ -0,0 +1,26 @@ 
+/* Round to nearest integer value, rounding halfway cases to even.
+   float version.
+   Copyright (C) 2019 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/>.  */
+
+#include <sysdep.h>
+
+	.section .text.sse4.1,"ax",@progbits
+ENTRY(__roundevenf_sse41)
+	roundss	$8, %xmm0, %xmm0
+	ret
+END(__roundevenf_sse41)
diff --git a/sysdeps/x86_64/fpu/multiarch/s_roundevenf.c b/sysdeps/x86_64/fpu/multiarch/s_roundevenf.c
new file mode 100644
index 0000000000..8ae1944d2b
--- /dev/null
+++ b/sysdeps/x86_64/fpu/multiarch/s_roundevenf.c
@@ -0,0 +1,31 @@ 
+/* Multiple versions of __roundevenf.
+   Copyright (C) 2019 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/>.  */
+
+#include <libm-alias-float.h>
+
+#define roundevenf __redirect_roundevenf
+#define __roundevenf __redirect___roundevenf
+#include <math.h>
+#undef roundevenf
+#undef __roundevenf
+
+#define SYMBOL_NAME roundevenf
+#include "ifunc-sse4_1.h"
+
+libc_ifunc_redirected (__redirect_roundevenf, __roundevenf, IFUNC_SELECTOR ());
+libm_alias_float (__roundeven, roundeven)
diff --git a/sysdeps/x86_64/fpu/s_roundevenl.S b/sysdeps/x86_64/fpu/s_roundevenl.S
new file mode 100644
index 0000000000..d179b1b603
--- /dev/null
+++ b/sysdeps/x86_64/fpu/s_roundevenl.S
@@ -0,0 +1,47 @@ 
+/* Round to nearest integer value, rounding halfway cases to even.
+   long double version.
+   Copyright (C) 2019 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/>.  */
+
+#include <libm-alias-ldouble.h>
+#include <machine/asm.h>
+
+ENTRY(__roundevenl)
+	fldt	8(%rsp)
+
+	fnstenv	-28(%rsp)		/* store fpu environment */
+
+	/* We use here %edx although only the low 1 bits are defined.
+	   But none of the operations should care and they are faster
+	   than the 16 bit operations.  */
+	movl	$0xf3ff,%edx		/* round to nearest (even) */
+	andl	-28(%rsp),%edx
+	movl	%edx,-32(%rsp)
+	fldcw	-32(%rsp)		/* load modified control word */
+
+	frndint				/* round */
+
+	/* Preserve "invalid" exceptions from sNaN input.  */
+	fnstsw
+	andl	$0x1, %eax
+	orl	%eax, -24(%rsp)
+
+	fldenv	-28(%rsp)		/* restore original environment */
+
+	ret
+END (__roundevenl)
+libm_alias_ldouble (__roundeven, roundeven)