ce426f
From 1ddf0e88cfea375eee1c7da2127a8520c02862b3 Mon Sep 17 00:00:00 2001
ce426f
From: Anton Blanchard <anton@samba.org>
ce426f
Date: Tue, 28 Jun 2016 21:59:40 +1000
ce426f
Subject: [PATCH] powerpc: Add a POWER8-optimized version of sinf()
ce426f
ce426f
This uses the implementation of sinf() in sysdeps/x86_64/fpu/s_sinf.S
ce426f
as inspiration.
ce426f
ce426f
(cherry picked from commit aa95fc13f5b02044eadc3af3d9e1c025f2e1edda)
ce426f
---
ce426f
 ChangeLog                                          |  10 +
ce426f
 sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile   |   3 +-
ce426f
 .../powerpc64/fpu/multiarch/s_sinf-power8.S        |  26 ++
ce426f
 .../powerpc/powerpc64/fpu/multiarch/s_sinf-ppc64.c |  26 ++
ce426f
 sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf.c   |  31 ++
ce426f
 sysdeps/powerpc/powerpc64/power8/fpu/s_sinf.S      | 519 +++++++++++++++++++++
ce426f
 6 files changed, 614 insertions(+), 1 deletion(-)
ce426f
 create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-power8.S
ce426f
 create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-ppc64.c
ce426f
 create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf.c
ce426f
 create mode 100644 sysdeps/powerpc/powerpc64/power8/fpu/s_sinf.S
ce426f
ce426f
diff --git a/ChangeLog b/ChangeLog
ce426f
index 6cb2578..6d6aab3 100644
ce426f
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile
ce426f
index 331763e..add1fb8 100644
ce426f
--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile
ce426f
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile
ce426f
@@ -25,7 +25,8 @@ libm-sysdep_routines += s_isnan-power7 s_isnan-power6x s_isnan-power6 \
ce426f
                        e_hypot-power7 e_hypotf-ppc64 e_hypotf-power7 \
ce426f
                        s_isnan-power8 s_isinf-power8 s_finite-power8 \
ce426f
                        s_llrint-power8 s_llround-power8 \
ce426f
-                       e_expf-power8 e_expf-ppc64
ce426f
+                       e_expf-power8 e_expf-ppc64 \
ce426f
+                       s_sinf-ppc64 s_sinf-power8
ce426f
 
ce426f
 CFLAGS-s_logbf-power7.c = -mcpu=power7
ce426f
 CFLAGS-s_logbl-power7.c = -mcpu=power7
ce426f
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-power8.S b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-power8.S
ce426f
new file mode 100644
ce426f
index 0000000..579019c
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-power8.S
ce426f
@@ -0,0 +1,26 @@
ce426f
+/* sinf().  PowerPC64/POWER8 version.
ce426f
+   Copyright (C) 2016 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+#undef weak_alias
ce426f
+#define weak_alias(a, b)
ce426f
+
ce426f
+#define __sinf __sinf_power8
ce426f
+
ce426f
+#include <sysdeps/powerpc/powerpc64/power8/fpu/s_sinf.S>
ce426f
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-ppc64.c b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-ppc64.c
ce426f
new file mode 100644
ce426f
index 0000000..eaf83fa
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf-ppc64.c
ce426f
@@ -0,0 +1,26 @@
ce426f
+/* sinf().  PowerPC64 default version.
ce426f
+   Copyright (C) 2016 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+#undef weak_alias
ce426f
+#define weak_alias(a, b)
ce426f
+
ce426f
+#define __sinf __sinf_ppc64
ce426f
+
ce426f
+#include <sysdeps/ieee754/flt-32/s_sinf.c>
ce426f
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf.c b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf.c
ce426f
new file mode 100644
ce426f
index 0000000..4269d58
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_sinf.c
ce426f
@@ -0,0 +1,31 @@
ce426f
+/* Multiple versions of sinf.
ce426f
+   Copyright (C) 2016 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <math.h>
ce426f
+#include <shlib-compat.h>
ce426f
+#include "init-arch.h"
ce426f
+
ce426f
+extern __typeof (__sinf) __sinf_ppc64 attribute_hidden;
ce426f
+extern __typeof (__sinf) __sinf_power8 attribute_hidden;
ce426f
+
ce426f
+libc_ifunc (__sinf,
ce426f
+            (hwcap2 & PPC_FEATURE2_ARCH_2_07)
ce426f
+            ? __sinf_power8
ce426f
+            : __sinf_ppc64);
ce426f
+
ce426f
+weak_alias (__sinf, sinf)
ce426f
diff --git a/sysdeps/powerpc/powerpc64/power8/fpu/s_sinf.S b/sysdeps/powerpc/powerpc64/power8/fpu/s_sinf.S
ce426f
new file mode 100644
ce426f
index 0000000..3b8f5af
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/power8/fpu/s_sinf.S
ce426f
@@ -0,0 +1,519 @@
ce426f
+/* Optimized sinf().  PowerPC64/POWER8 version.
ce426f
+   Copyright (C) 2016 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+#define _ERRNO_H	1
ce426f
+#include <bits/errno.h>
ce426f
+
ce426f
+#define FRAMESIZE (FRAME_MIN_SIZE+16)
ce426f
+
ce426f
+#define FLOAT_EXPONENT_SHIFT	23
ce426f
+#define FLOAT_EXPONENT_BIAS	127
ce426f
+#define INTEGER_BITS		3
ce426f
+
ce426f
+#define PI_4		0x3f490fdb	/* PI/4 */
ce426f
+#define NINEPI_4	0x40e231d6	/* 9 * PI/4 */
ce426f
+#define TWO_PN5		0x3d000000	/* 2^-5 */
ce426f
+#define TWO_PN27	0x32000000	/* 2^-27 */
ce426f
+#define INFINITY	0x7f800000
ce426f
+#define TWO_P23		0x4b000000	/* 2^27 */
ce426f
+#define FX_FRACTION_1_28 0x9249250	/* 0x100000000 / 28 + 1 */
ce426f
+
ce426f
+	/* Implements the function
ce426f
+
ce426f
+	   float [fp1] sinf (float [fp1] x)  */
ce426f
+
ce426f
+	.machine power8
ce426f
+EALIGN(__sinf, 4, 0)
ce426f
+	addis	r9,r2,L(anchor)@toc@ha
ce426f
+	addi	r9,r9,L(anchor)@toc@l
ce426f
+
ce426f
+	lis	r4,PI_4@h
ce426f
+	ori	r4,r4,PI_4@l
ce426f
+
ce426f
+	xscvdpspn v0,v1
ce426f
+	mfvsrd	r8,v0
ce426f
+	rldicl	r3,r8,32,33		/* Remove sign bit.  */
ce426f
+
ce426f
+	cmpw	r3,r4
ce426f
+	bge	L(greater_or_equal_pio4)
ce426f
+
ce426f
+	lis	r4,TWO_PN5@h
ce426f
+	ori	r4,r4,TWO_PN5@l
ce426f
+
ce426f
+	cmpw	r3,r4
ce426f
+	blt	L(less_2pn5)
ce426f
+
ce426f
+	/* Chebyshev polynomial of the form:
ce426f
+	 * x+x^3*(S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4)))).  */
ce426f
+
ce426f
+	lfd	fp9,(L(S0)-L(anchor))(r9)
ce426f
+	lfd	fp10,(L(S1)-L(anchor))(r9)
ce426f
+	lfd	fp11,(L(S2)-L(anchor))(r9)
ce426f
+	lfd	fp12,(L(S3)-L(anchor))(r9)
ce426f
+	lfd	fp13,(L(S4)-L(anchor))(r9)
ce426f
+
ce426f
+	fmul	fp2,fp1,fp1		/* x^2 */
ce426f
+	fmul	fp3,fp2,fp1		/* x^3 */
ce426f
+
ce426f
+	fmadd	fp4,fp2,fp13,fp12	/* S3+x^2*S4 */
ce426f
+	fmadd	fp4,fp2,fp4,fp11	/* S2+x^2*(S3+x^2*S4) */
ce426f
+	fmadd	fp4,fp2,fp4,fp10	/* S1+x^2*(S2+x^2*(S3+x^2*S4)) */
ce426f
+	fmadd	fp4,fp2,fp4,fp9		/* S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4))) */
ce426f
+	fmadd	fp1,fp3,fp4,fp1		/* x+x^3*(S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4)))) */
ce426f
+	frsp	fp1,fp1			/* Round to single precision.  */
ce426f
+
ce426f
+	blr
ce426f
+
ce426f
+	.balign 16
ce426f
+L(greater_or_equal_pio4):
ce426f
+	lis	r4,NINEPI_4@h
ce426f
+	ori	r4,r4,NINEPI_4@l
ce426f
+	cmpw	r3,r4
ce426f
+	bge	L(greater_or_equal_9pio4)
ce426f
+
ce426f
+	/* Calculate quotient of |x|/(PI/4).  */
ce426f
+	lfd	fp2,(L(invpio4)-L(anchor))(r9)
ce426f
+	fabs	fp1,fp1			/* |x| */
ce426f
+	fmul	fp2,fp1,fp2		/* |x|/(PI/4) */
ce426f
+	fctiduz	fp2,fp2
ce426f
+	mfvsrd	r3,v2			/* n = |x| mod PI/4 */
ce426f
+
ce426f
+	/* Now use that quotient to find |x| mod (PI/2).  */
ce426f
+	addi	r7,r3,1
ce426f
+	rldicr	r5,r7,2,60		/* ((n+1) >> 1) << 3 */
ce426f
+	addi	r6,r9,(L(pio2_table)-L(anchor))
ce426f
+	lfdx	fp4,r5,r6
ce426f
+	fsub	fp1,fp1,fp4
ce426f
+
ce426f
+	.balign 16
ce426f
+L(reduced):
ce426f
+	/* Now we are in the range -PI/4 to PI/4.  */
ce426f
+
ce426f
+	/* Work out if we are in a positive or negative primary interval.  */
ce426f
+	rldicl	r4,r7,62,63		/* ((n+1) >> 2) & 1 */
ce426f
+
ce426f
+	/* We are operating on |x|, so we need to add back the original
ce426f
+	   sign.  */
ce426f
+	rldicl	r8,r8,33,63		/* (x >> 31) & 1, ie the sign bit.  */
ce426f
+	xor	r4,r4,r8		/* 0 if result should be positive,
ce426f
+					   1 if negative.  */
ce426f
+
ce426f
+	/* Load a 1.0 or -1.0.  */
ce426f
+	addi	r5,r9,(L(ones)-L(anchor))
ce426f
+	sldi	r4,r4,3
ce426f
+	lfdx	fp0,r4,r5
ce426f
+
ce426f
+	/* Are we in the primary interval of sin or cos?  */
ce426f
+	andi.	r4,r7,0x2
ce426f
+	bne	L(cos)
ce426f
+
ce426f
+	/* Chebyshev polynomial of the form:
ce426f
+	   x+x^3*(S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4)))).  */
ce426f
+
ce426f
+	lfd	fp9,(L(S0)-L(anchor))(r9)
ce426f
+	lfd	fp10,(L(S1)-L(anchor))(r9)
ce426f
+	lfd	fp11,(L(S2)-L(anchor))(r9)
ce426f
+	lfd	fp12,(L(S3)-L(anchor))(r9)
ce426f
+	lfd	fp13,(L(S4)-L(anchor))(r9)
ce426f
+
ce426f
+	fmul	fp2,fp1,fp1		/* x^2 */
ce426f
+	fmul	fp3,fp2,fp1		/* x^3 */
ce426f
+
ce426f
+	fmadd	fp4,fp2,fp13,fp12	/* S3+x^2*S4 */
ce426f
+	fmadd	fp4,fp2,fp4,fp11	/* S2+x^2*(S3+x^2*S4) */
ce426f
+	fmadd	fp4,fp2,fp4,fp10	/* S1+x^2*(S2+x^2*(S3+x^2*S4)) */
ce426f
+	fmadd	fp4,fp2,fp4,fp9		/* S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4))) */
ce426f
+	fmadd	fp4,fp3,fp4,fp1		/* x+x^3*(S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4)))) */
ce426f
+	fmul	fp4,fp4,fp0		/* Add in the sign.  */
ce426f
+	frsp	fp1,fp4			/* Round to single precision.  */
ce426f
+
ce426f
+	blr
ce426f
+
ce426f
+	.balign 16
ce426f
+L(cos):
ce426f
+	/* Chebyshev polynomial of the form:
ce426f
+	   1.0+x^2*(C0+x^2*(C1+x^2*(C2+x^2*(C3+x^2*C4)))).  */
ce426f
+
ce426f
+	lfd	fp9,(L(C0)-L(anchor))(r9)
ce426f
+	lfd	fp10,(L(C1)-L(anchor))(r9)
ce426f
+	lfd	fp11,(L(C2)-L(anchor))(r9)
ce426f
+	lfd	fp12,(L(C3)-L(anchor))(r9)
ce426f
+	lfd	fp13,(L(C4)-L(anchor))(r9)
ce426f
+
ce426f
+	fmul	fp2,fp1,fp1		/* x^2 */
ce426f
+	lfd	fp3,(L(DPone)-L(anchor))(r9)
ce426f
+
ce426f
+	fmadd	fp4,fp2,fp13,fp12	/* C3+x^2*C4 */
ce426f
+	fmadd	fp4,fp2,fp4,fp11	/* C2+x^2*(C3+x^2*C4) */
ce426f
+	fmadd	fp4,fp2,fp4,fp10	/* C1+x^2*(C2+x^2*(C3+x^2*C4)) */
ce426f
+	fmadd	fp4,fp2,fp4,fp9		/* C0+x^2*(C1+x^2*(C2+x^2*(C3+x^2*C4))) */
ce426f
+	fmadd	fp4,fp2,fp4,fp3		/* 1.0 + x^2*(C0+x^2*(C1+x^2*(C2+x^2*(C3+x^2*C4)))) */
ce426f
+	fmul	fp4,fp4,fp0		/* Add in the sign.  */
ce426f
+	frsp	fp1,fp4			/* Round to single precision.  */
ce426f
+
ce426f
+	blr
ce426f
+
ce426f
+	.balign 16
ce426f
+L(greater_or_equal_9pio4):
ce426f
+	lis	r4,INFINITY@h
ce426f
+	ori	r4,r4,INFINITY@l
ce426f
+	cmpw	r3,r4
ce426f
+	bge	L(inf_or_nan)
ce426f
+
ce426f
+	lis	r4,TWO_P23@h
ce426f
+	ori	r4,r4,TWO_P23@l
ce426f
+	cmpw	r3,r4
ce426f
+	bge	L(greater_or_equal_2p23)
ce426f
+
ce426f
+	fabs	fp1,fp1			/* |x| */
ce426f
+
ce426f
+	/* Calculate quotient of |x|/(PI/4).  */
ce426f
+	lfd	fp2,(L(invpio4)-L(anchor))(r9)
ce426f
+
ce426f
+	lfd	fp3,(L(DPone)-L(anchor))(r9)
ce426f
+	lfd	fp4,(L(DPhalf)-L(anchor))(r9)
ce426f
+	fmul	fp2,fp1,fp2		/* |x|/(PI/4) */
ce426f
+	friz	fp2,fp2			/* n = floor(|x|/(PI/4)) */
ce426f
+
ce426f
+	/* Calculate (n + 1) / 2.  */
ce426f
+	fadd	fp2,fp2,fp3		/* n + 1 */
ce426f
+	fmul	fp3,fp2,fp4		/* (n + 1) / 2 */
ce426f
+	friz	fp3,fp3
ce426f
+
ce426f
+	lfd	fp4,(L(pio2hi)-L(anchor))(r9)
ce426f
+	lfd	fp5,(L(pio2lo)-L(anchor))(r9)
ce426f
+
ce426f
+	fmul	fp6,fp4,fp3
ce426f
+	fadd	fp6,fp6,fp1
ce426f
+	fmadd	fp1,fp5,fp3,fp6
ce426f
+
ce426f
+	fctiduz	fp2,fp2
ce426f
+	mfvsrd	r7,v2			/* n + 1 */
ce426f
+
ce426f
+	b	L(reduced)
ce426f
+
ce426f
+	.balign 16
ce426f
+L(inf_or_nan):
ce426f
+	bne	L(skip_errno_setting)	/* Is a NAN?  */
ce426f
+
ce426f
+	/* We delayed the creation of the stack frame, as well as the saving of
ce426f
+	   the link register, because only at this point, we are sure that
ce426f
+	   doing so is actually needed.  */
ce426f
+
ce426f
+	stfd	fp1,-8(r1)
ce426f
+
ce426f
+	/* Save the link register.  */
ce426f
+	mflr	r0
ce426f
+	std	r0,16(r1)
ce426f
+	cfi_offset(lr, 16)
ce426f
+
ce426f
+	/* Create the stack frame.  */
ce426f
+	stdu	r1,-FRAMESIZE(r1)
ce426f
+	cfi_adjust_cfa_offset(FRAMESIZE)
ce426f
+
ce426f
+	bl	JUMPTARGET(__errno_location)
ce426f
+	nop
ce426f
+
ce426f
+	/* Restore the stack frame.  */
ce426f
+	addi	r1,r1,FRAMESIZE
ce426f
+	cfi_adjust_cfa_offset(-FRAMESIZE)
ce426f
+	/* Restore the link register.  */
ce426f
+	ld	r0,16(r1)
ce426f
+	mtlr	r0
ce426f
+
ce426f
+	lfd	fp1,-8(r1)
ce426f
+
ce426f
+	/* errno = EDOM */
ce426f
+	li	r4,EDOM
ce426f
+	stw	r4,0(r3)
ce426f
+
ce426f
+L(skip_errno_setting):
ce426f
+	fsub	fp1,fp1,fp1		/* x - x */
ce426f
+	blr
ce426f
+
ce426f
+	.balign 16
ce426f
+L(greater_or_equal_2p23):
ce426f
+	fabs	fp1,fp1
ce426f
+
ce426f
+	srwi	r4,r3,FLOAT_EXPONENT_SHIFT
ce426f
+	subi	r4,r4,FLOAT_EXPONENT_BIAS
ce426f
+
ce426f
+	/* We reduce the input modulo pi/4, so we need 3 bits of integer
ce426f
+	   to determine where in 2*pi we are. Index into our array
ce426f
+	   accordingly.  */
ce426f
+	addi r4,r4,INTEGER_BITS
ce426f
+
ce426f
+	/* To avoid an expensive divide, for the range we care about (0 - 127)
ce426f
+	   we can transform x/28 into:
ce426f
+
ce426f
+	   x/28 = (x * ((0x100000000 / 28) + 1)) >> 32
ce426f
+
ce426f
+	   mulhwu returns the top 32 bits of the 64 bit result, doing the
ce426f
+	   shift for us in the same instruction. The top 32 bits are undefined,
ce426f
+	   so we have to mask them.  */
ce426f
+
ce426f
+	lis	r6,FX_FRACTION_1_28@h
ce426f
+	ori	r6,r6,FX_FRACTION_1_28@l
ce426f
+	mulhwu	r5,r4,r6
ce426f
+	clrldi	r5,r5,32
ce426f
+
ce426f
+	/* Get our pointer into the invpio4_table array.  */
ce426f
+	sldi	r4,r5,3
ce426f
+	addi	r6,r9,(L(invpio4_table)-L(anchor))
ce426f
+	add	r4,r4,r6
ce426f
+
ce426f
+	lfd	fp2,0(r4)
ce426f
+	lfd	fp3,8(r4)
ce426f
+	lfd	fp4,16(r4)
ce426f
+	lfd	fp5,24(r4)
ce426f
+
ce426f
+	fmul	fp6,fp2,fp1
ce426f
+	fmul	fp7,fp3,fp1
ce426f
+	fmul	fp8,fp4,fp1
ce426f
+	fmul	fp9,fp5,fp1
ce426f
+
ce426f
+	/* Mask off larger integer bits in highest double word that we don't
ce426f
+	   care about to avoid losing precision when combining with smaller
ce426f
+	   values.  */
ce426f
+	fctiduz	fp10,fp6
ce426f
+	mfvsrd	r7,v10
ce426f
+	rldicr	r7,r7,0,(63-INTEGER_BITS)
ce426f
+	mtvsrd	v10,r7
ce426f
+	fcfidu	fp10,fp10		/* Integer bits.  */
ce426f
+
ce426f
+	fsub	fp6,fp6,fp10		/* highest -= integer bits */
ce426f
+
ce426f
+	/* Work out the integer component, rounded down. Use the top two
ce426f
+	   limbs for this.  */
ce426f
+	fadd	fp10,fp6,fp7		/* highest + higher */
ce426f
+
ce426f
+	fctiduz	fp10,fp10
ce426f
+	mfvsrd	r7,v10
ce426f
+	andi.	r0,r7,1
ce426f
+	fcfidu	fp10,fp10
ce426f
+
ce426f
+	/* Subtract integer component from highest limb.  */
ce426f
+	fsub	fp12,fp6,fp10
ce426f
+
ce426f
+	beq	L(even_integer)
ce426f
+
ce426f
+	/* Our integer component is odd, so we are in the -PI/4 to 0 primary
ce426f
+	   region. We need to shift our result down by PI/4, and to do this
ce426f
+	   in the mod (4/PI) space we simply subtract 1.  */
ce426f
+	lfd	fp11,(L(DPone)-L(anchor))(r9)
ce426f
+	fsub	fp12,fp12,fp11
ce426f
+
ce426f
+	/* Now add up all the limbs in order.  */
ce426f
+	fadd	fp12,fp12,fp7
ce426f
+	fadd	fp12,fp12,fp8
ce426f
+	fadd	fp12,fp12,fp9
ce426f
+
ce426f
+	/* And finally multiply by pi/4.  */
ce426f
+	lfd	fp13,(L(pio4)-L(anchor))(r9)
ce426f
+	fmul	fp1,fp12,fp13
ce426f
+
ce426f
+	addi	r7,r7,1
ce426f
+	b	L(reduced)
ce426f
+
ce426f
+L(even_integer):
ce426f
+	lfd	fp11,(L(DPone)-L(anchor))(r9)
ce426f
+
ce426f
+	/* Now add up all the limbs in order.  */
ce426f
+	fadd	fp12,fp12,fp7
ce426f
+	fadd	fp12,r12,fp8
ce426f
+	fadd	fp12,r12,fp9
ce426f
+
ce426f
+	/* We need to check if the addition of all the limbs resulted in us
ce426f
+	   overflowing 1.0.  */
ce426f
+	fcmpu	0,fp12,fp11
ce426f
+	bgt	L(greater_than_one)
ce426f
+
ce426f
+	/* And finally multiply by pi/4.  */
ce426f
+	lfd	fp13,(L(pio4)-L(anchor))(r9)
ce426f
+	fmul	fp1,fp12,fp13
ce426f
+
ce426f
+	addi	r7,r7,1
ce426f
+	b	L(reduced)
ce426f
+
ce426f
+L(greater_than_one):
ce426f
+	/* We did overflow 1.0 when adding up all the limbs. Add 1.0 to our
ce426f
+	   integer, and subtract 1.0 from our result. Since that makes the
ce426f
+	   integer component odd, we need to subtract another 1.0 as
ce426f
+	   explained above.  */
ce426f
+	addi	r7,r7,1
ce426f
+
ce426f
+	lfd	fp11,(L(DPtwo)-L(anchor))(r9)
ce426f
+	fsub	fp12,fp12,fp11
ce426f
+
ce426f
+	/* And finally multiply by pi/4.  */
ce426f
+	lfd	fp13,(L(pio4)-L(anchor))(r9)
ce426f
+	fmul	fp1,fp12,fp13
ce426f
+
ce426f
+	addi	r7,r7,1
ce426f
+	b	L(reduced)
ce426f
+
ce426f
+	.balign 16
ce426f
+L(less_2pn5):
ce426f
+	lis	r4,TWO_PN27@h
ce426f
+	ori	r4,r4,TWO_PN27@l
ce426f
+
ce426f
+	cmpw	r3,r4
ce426f
+	blt	L(less_2pn27)
ce426f
+
ce426f
+	/* A simpler Chebyshev approximation is close enough for this range:
ce426f
+	   x+x^3*(SS0+x^2*SS1).  */
ce426f
+
ce426f
+	lfd	fp10,(L(SS0)-L(anchor))(r9)
ce426f
+	lfd	fp11,(L(SS1)-L(anchor))(r9)
ce426f
+
ce426f
+	fmul	fp2,fp1,fp1		/* x^2 */
ce426f
+	fmul	fp3,fp2,fp1		/* x^3 */
ce426f
+
ce426f
+	fmadd	fp4,fp2,fp11,fp10	/* SS0+x^2*SS1 */
ce426f
+	fmadd	fp1,fp3,fp4,fp1		/* x+x^3*(SS0+x^2*SS1) */
ce426f
+
ce426f
+	frsp	fp1,fp1			/* Round to single precision.  */
ce426f
+
ce426f
+	blr
ce426f
+
ce426f
+	.balign 16
ce426f
+L(less_2pn27):
ce426f
+	cmpwi	r3,0
ce426f
+	beq	L(zero)
ce426f
+
ce426f
+	/* Handle some special cases:
ce426f
+
ce426f
+	   sinf(subnormal) raises inexact/underflow
ce426f
+	   sinf(min_normalized) raises inexact/underflow
ce426f
+	   sinf(normalized) raises inexact.  */
ce426f
+
ce426f
+	lfd	fp2,(L(small)-L(anchor))(r9)
ce426f
+
ce426f
+	fmul	fp2,fp1,fp2		/* x * small */
ce426f
+	fsub	fp1,fp1,fp2		/* x - x * small */
ce426f
+
ce426f
+	frsp	fp1,fp1
ce426f
+
ce426f
+	blr
ce426f
+
ce426f
+	.balign 16
ce426f
+L(zero):
ce426f
+	blr
ce426f
+
ce426f
+END (__sinf)
ce426f
+
ce426f
+	.section .rodata, "a"
ce426f
+
ce426f
+	.balign 8
ce426f
+
ce426f
+L(anchor):
ce426f
+
ce426f
+	/* Chebyshev constants for sin, range -PI/4 - PI/4.  */
ce426f
+L(S0):	.8byte	0xbfc5555555551cd9
ce426f
+L(S1):	.8byte	0x3f81111110c2688b
ce426f
+L(S2):	.8byte	0xbf2a019f8b4bd1f9
ce426f
+L(S3):	.8byte	0x3ec71d7264e6b5b4
ce426f
+L(S4):	.8byte	0xbe5a947e1674b58a
ce426f
+
ce426f
+	/* Chebyshev constants for sin, range 2^-27 - 2^-5.  */
ce426f
+L(SS0):	.8byte	0xbfc555555543d49d
ce426f
+L(SS1):	.8byte	0x3f8110f475cec8c5
ce426f
+
ce426f
+	/* Chebyshev constants for cos, range -PI/4 - PI/4.  */
ce426f
+L(C0):	.8byte	0xbfdffffffffe98ae
ce426f
+L(C1):	.8byte	0x3fa55555545c50c7
ce426f
+L(C2):	.8byte	0xbf56c16b348b6874
ce426f
+L(C3):	.8byte	0x3efa00eb9ac43cc0
ce426f
+L(C4):	.8byte	0xbe923c97dd8844d7
ce426f
+
ce426f
+L(invpio2):
ce426f
+	.8byte	0x3fe45f306dc9c883	/* 2/PI */
ce426f
+
ce426f
+L(invpio4):
ce426f
+	.8byte	0x3ff45f306dc9c883	/* 4/PI */
ce426f
+
ce426f
+L(invpio4_table):
ce426f
+	.8byte	0x0000000000000000
ce426f
+	.8byte	0x3ff45f306c000000
ce426f
+	.8byte	0x3e3c9c882a000000
ce426f
+	.8byte	0x3c54fe13a8000000
ce426f
+	.8byte	0x3aaf47d4d0000000
ce426f
+	.8byte	0x38fbb81b6c000000
ce426f
+	.8byte	0x3714acc9e0000000
ce426f
+	.8byte	0x3560e4107c000000
ce426f
+	.8byte	0x33bca2c756000000
ce426f
+	.8byte	0x31fbd778ac000000
ce426f
+	.8byte	0x300b7246e0000000
ce426f
+	.8byte	0x2e5d2126e8000000
ce426f
+	.8byte	0x2c97003248000000
ce426f
+	.8byte	0x2ad77504e8000000
ce426f
+	.8byte	0x290921cfe0000000
ce426f
+	.8byte	0x274deb1cb0000000
ce426f
+	.8byte	0x25829a73e0000000
ce426f
+	.8byte	0x23fd1046be000000
ce426f
+	.8byte	0x2224baed10000000
ce426f
+	.8byte	0x20709d338e000000
ce426f
+	.8byte	0x1e535a2f80000000
ce426f
+	.8byte	0x1cef904e64000000
ce426f
+	.8byte	0x1b0d639830000000
ce426f
+	.8byte	0x1964ce7d24000000
ce426f
+	.8byte	0x17b908bf16000000
ce426f
+
ce426f
+L(pio4):
ce426f
+	.8byte	0x3fe921fb54442d18	/* PI/4 */
ce426f
+
ce426f
+/* PI/2 as a sum of two doubles. We only use 32 bits of the upper limb
ce426f
+   to avoid losing significant bits when multiplying with up to
ce426f
+   (2^22)/(pi/2).  */
ce426f
+L(pio2hi):
ce426f
+	.8byte	0xbff921fb54400000
ce426f
+
ce426f
+L(pio2lo):
ce426f
+	.8byte	0xbdd0b4611a626332
ce426f
+
ce426f
+L(pio2_table):
ce426f
+	.8byte	0
ce426f
+	.8byte	0x3ff921fb54442d18	/* 1 * PI/2 */
ce426f
+	.8byte	0x400921fb54442d18	/* 2 * PI/2 */
ce426f
+	.8byte	0x4012d97c7f3321d2	/* 3 * PI/2 */
ce426f
+	.8byte	0x401921fb54442d18	/* 4 * PI/2 */
ce426f
+	.8byte	0x401f6a7a2955385e	/* 5 * PI/2 */
ce426f
+	.8byte	0x4022d97c7f3321d2	/* 6 * PI/2 */
ce426f
+	.8byte	0x4025fdbbe9bba775	/* 7 * PI/2 */
ce426f
+	.8byte	0x402921fb54442d18	/* 8 * PI/2 */
ce426f
+	.8byte	0x402c463abeccb2bb	/* 9 * PI/2 */
ce426f
+	.8byte	0x402f6a7a2955385e	/* 10 * PI/2 */
ce426f
+
ce426f
+L(small):
ce426f
+	.8byte	0x3cd0000000000000	/* 2^-50 */
ce426f
+
ce426f
+L(ones):
ce426f
+	.8byte	0x3ff0000000000000	/* +1.0 */
ce426f
+	.8byte	0xbff0000000000000	/* -1.0 */
ce426f
+
ce426f
+L(DPhalf):
ce426f
+	.8byte	0x3fe0000000000000	/* 0.5 */
ce426f
+
ce426f
+L(DPone):
ce426f
+	.8byte	0x3ff0000000000000	/* 1.0 */
ce426f
+
ce426f
+L(DPtwo):
ce426f
+	.8byte	0x4000000000000000	/* 2.0 */
ce426f
+
ce426f
+weak_alias(__sinf, sinf)
ce426f
-- 
ce426f
2.1.0
ce426f