about summary refs log tree commit diff
path: root/sysdeps/powerpc/lshift.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/lshift.S')
-rw-r--r--sysdeps/powerpc/lshift.S123
1 files changed, 123 insertions, 0 deletions
diff --git a/sysdeps/powerpc/lshift.S b/sysdeps/powerpc/lshift.S
new file mode 100644
index 0000000000..b1487a1c17
--- /dev/null
+++ b/sysdeps/powerpc/lshift.S
@@ -0,0 +1,123 @@
+/* Shift a limb left, low level routine.
+   Copyright (C) 1996, 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <sysdep.h>
+
+/* mp_limb_t mpn_lshift (mp_ptr wp, mp_srcptr up, mp_size_t usize,
+  			 unsigned int cnt)  */
+
+EALIGN(__mpn_lshift,3,0)
+	mtctr	%r5		# copy size into CTR
+	cmplwi	%cr0,%r5,16	# is size < 16
+	slwi	%r0,%r5,2
+	add	%r7,%r3,%r0	# make r7 point at end of res
+	add	%r4,%r4,%r0	# make r4 point at end of s1
+	lwzu	%r11,-4(%r4)	# load first s1 limb
+	subfic	%r8,%r6,32
+	srw	%r3,%r11,%r8	# compute function return value
+	bge	%cr0,L(big)	# branch if size >= 16
+
+	bdz	L(end1)
+
+0:	lwzu	%r10,-4(%r4)
+	slw	%r9,%r11,%r6
+	srw	%r12,%r10,%r8
+	or	%r9,%r9,%r12
+	stwu	%r9,-4(%r7)
+	bdz	L(end2)
+	lwzu	%r11,-4(%r4)
+	slw	%r9,%r10,%r6
+	srw	%r12,%r11,%r8
+	or	%r9,%r9,%r12
+	stwu	%r9,-4(%r7)
+	bdnz	0b
+
+L(end1):slw	%r0,%r11,%r6
+	stw	%r0,-4(%r7)
+	blr
+
+
+/* Guaranteed not to succeed.  */
+L(boom): tweq    %r0,%r0
+
+/* We imitate a case statement, by using (yuk!) fixed-length code chunks,
+   of size 4*12 bytes.  We have to do this (or something) to make this PIC.  */
+L(big):	mflr    %r9
+	bltl-   %cr0,L(boom)	# Never taken, only used to set LR.
+	slwi    %r10,%r6,4
+	mflr    %r12
+	add     %r10,%r12,%r10
+	slwi	%r8,%r6,5
+	add     %r10,%r8,%r10
+	mtctr   %r10
+	addi	%r5,%r5,-1
+	mtlr    %r9
+	bctr
+
+L(end2):slw	%r0,%r10,%r6
+	stw	%r0,-4(%r7)
+	blr
+
+#define DO_LSHIFT(n) \
+	mtctr	%r5;							\
+0:	lwzu	%r10,-4(%r4);						\
+	slwi	%r9,%r11,n;						\
+	inslwi	%r9,%r10,n,32-n;					\
+	stwu	%r9,-4(%r7);						\
+	bdz-	L(end2);						\
+	lwzu	%r11,-4(%r4);						\
+	slwi	%r9,%r10,n;						\
+	inslwi	%r9,%r11,n,32-n;					\
+	stwu	%r9,-4(%r7);						\
+	bdnz	0b;							\
+	b	L(end1)
+
+	DO_LSHIFT(1)
+	DO_LSHIFT(2)
+	DO_LSHIFT(3)
+	DO_LSHIFT(4)
+	DO_LSHIFT(5)
+	DO_LSHIFT(6)
+	DO_LSHIFT(7)
+	DO_LSHIFT(8)
+	DO_LSHIFT(9)
+	DO_LSHIFT(10)
+	DO_LSHIFT(11)
+	DO_LSHIFT(12)
+	DO_LSHIFT(13)
+	DO_LSHIFT(14)
+	DO_LSHIFT(15)
+	DO_LSHIFT(16)
+	DO_LSHIFT(17)
+	DO_LSHIFT(18)
+	DO_LSHIFT(19)
+	DO_LSHIFT(20)
+	DO_LSHIFT(21)
+	DO_LSHIFT(22)
+	DO_LSHIFT(23)
+	DO_LSHIFT(24)
+	DO_LSHIFT(25)
+	DO_LSHIFT(26)
+	DO_LSHIFT(27)
+	DO_LSHIFT(28)
+	DO_LSHIFT(29)
+	DO_LSHIFT(30)
+	DO_LSHIFT(31)
+
+END(__mpn_lshift)