xref: /haiku/src/system/libroot/posix/glibc/arch/m68k/lshift.S (revision dd68e9e8b4273bb7f91680e04f5cda6ec74a73a8)
1*dd68e9e8SFrançois Revol/* mc68020 __mpn_lshift -- Shift left a low-level natural-number integer.
2*dd68e9e8SFrançois Revol
3*dd68e9e8SFrançois RevolCopyright (C) 1996, 1998 Free Software Foundation, Inc.
4*dd68e9e8SFrançois Revol
5*dd68e9e8SFrançois RevolThis file is part of the GNU MP Library.
6*dd68e9e8SFrançois Revol
7*dd68e9e8SFrançois RevolThe GNU MP Library is free software; you can redistribute it and/or modify
8*dd68e9e8SFrançois Revolit under the terms of the GNU Lesser General Public License as published by
9*dd68e9e8SFrançois Revolthe Free Software Foundation; either version 2.1 of the License, or (at your
10*dd68e9e8SFrançois Revoloption) any later version.
11*dd68e9e8SFrançois Revol
12*dd68e9e8SFrançois RevolThe GNU MP Library is distributed in the hope that it will be useful, but
13*dd68e9e8SFrançois RevolWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14*dd68e9e8SFrançois Revolor FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15*dd68e9e8SFrançois RevolLicense for more details.
16*dd68e9e8SFrançois Revol
17*dd68e9e8SFrançois RevolYou should have received a copy of the GNU Lesser General Public License
18*dd68e9e8SFrançois Revolalong with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19*dd68e9e8SFrançois Revolthe Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20*dd68e9e8SFrançois RevolMA 02111-1307, USA. */
21*dd68e9e8SFrançois Revol
22*dd68e9e8SFrançois Revol/*
23*dd68e9e8SFrançois Revol  INPUT PARAMETERS
24*dd68e9e8SFrançois Revol  res_ptr	(sp + 4)
25*dd68e9e8SFrançois Revol  s_ptr		(sp + 8)
26*dd68e9e8SFrançois Revol  s_size	(sp + 16)
27*dd68e9e8SFrançois Revol  cnt		(sp + 12)
28*dd68e9e8SFrançois Revol*/
29*dd68e9e8SFrançois Revol
30*dd68e9e8SFrançois Revol#include "sysdep.h"
31*dd68e9e8SFrançois Revol#include "asm-syntax.h"
32*dd68e9e8SFrançois Revol
33*dd68e9e8SFrançois Revol#define res_ptr a1
34*dd68e9e8SFrançois Revol#define s_ptr a0
35*dd68e9e8SFrançois Revol#define s_size d6
36*dd68e9e8SFrançois Revol#define cnt d4
37*dd68e9e8SFrançois Revol
38*dd68e9e8SFrançois Revol	TEXT
39*dd68e9e8SFrançois RevolENTRY(__mpn_lshift)
40*dd68e9e8SFrançois Revol
41*dd68e9e8SFrançois Revol/* Save used registers on the stack.  */
42*dd68e9e8SFrançois Revol	moveml	R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
43*dd68e9e8SFrançois Revol
44*dd68e9e8SFrançois Revol/* Copy the arguments to registers.  */
45*dd68e9e8SFrançois Revol	movel	MEM_DISP(sp,28),R(res_ptr)
46*dd68e9e8SFrançois Revol	movel	MEM_DISP(sp,32),R(s_ptr)
47*dd68e9e8SFrançois Revol	movel	MEM_DISP(sp,36),R(s_size)
48*dd68e9e8SFrançois Revol	movel	MEM_DISP(sp,40),R(cnt)
49*dd68e9e8SFrançois Revol
50*dd68e9e8SFrançois Revol	moveql	#1,R(d5)
51*dd68e9e8SFrançois Revol	cmpl	R(d5),R(cnt)
52*dd68e9e8SFrançois Revol	bne	L(Lnormal)
53*dd68e9e8SFrançois Revol	cmpl	R(s_ptr),R(res_ptr)
54*dd68e9e8SFrançois Revol	bls	L(Lspecial)		/* jump if s_ptr >= res_ptr */
55*dd68e9e8SFrançois Revol#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
56*dd68e9e8SFrançois Revol	lea	MEM_INDX1(s_ptr,s_size,l,4),R(a2)
57*dd68e9e8SFrançois Revol#else /* not mc68020 */
58*dd68e9e8SFrançois Revol	movel	R(s_size),R(d0)
59*dd68e9e8SFrançois Revol	asll	#2,R(d0)
60*dd68e9e8SFrançois Revol	lea	MEM_INDX(s_ptr,d0,l),R(a2)
61*dd68e9e8SFrançois Revol#endif
62*dd68e9e8SFrançois Revol	cmpl	R(res_ptr),R(a2)
63*dd68e9e8SFrançois Revol	bls	L(Lspecial)		/* jump if res_ptr >= s_ptr + s_size */
64*dd68e9e8SFrançois Revol
65*dd68e9e8SFrançois RevolL(Lnormal:)
66*dd68e9e8SFrançois Revol	moveql	#32,R(d5)
67*dd68e9e8SFrançois Revol	subl	R(cnt),R(d5)
68*dd68e9e8SFrançois Revol
69*dd68e9e8SFrançois Revol#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
70*dd68e9e8SFrançois Revol	lea	MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
71*dd68e9e8SFrançois Revol	lea	MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
72*dd68e9e8SFrançois Revol#else /* not mc68000 */
73*dd68e9e8SFrançois Revol	movel	R(s_size),R(d0)
74*dd68e9e8SFrançois Revol	asll	#2,R(d0)
75*dd68e9e8SFrançois Revol	addl	R(s_size),R(s_ptr)
76*dd68e9e8SFrançois Revol	addl	R(s_size),R(res_ptr)
77*dd68e9e8SFrançois Revol#endif
78*dd68e9e8SFrançois Revol	movel	MEM_PREDEC(s_ptr),R(d2)
79*dd68e9e8SFrançois Revol	movel	R(d2),R(d0)
80*dd68e9e8SFrançois Revol	lsrl	R(d5),R(d0)		/* compute carry limb */
81*dd68e9e8SFrançois Revol
82*dd68e9e8SFrançois Revol	lsll	R(cnt),R(d2)
83*dd68e9e8SFrançois Revol	movel	R(d2),R(d1)
84*dd68e9e8SFrançois Revol	subql	#1,R(s_size)
85*dd68e9e8SFrançois Revol	beq	L(Lend)
86*dd68e9e8SFrançois Revol	lsrl	#1,R(s_size)
87*dd68e9e8SFrançois Revol	bcs	L(L1)
88*dd68e9e8SFrançois Revol	subql	#1,R(s_size)
89*dd68e9e8SFrançois Revol
90*dd68e9e8SFrançois RevolL(Loop:)
91*dd68e9e8SFrançois Revol	movel	MEM_PREDEC(s_ptr),R(d2)
92*dd68e9e8SFrançois Revol	movel	R(d2),R(d3)
93*dd68e9e8SFrançois Revol	lsrl	R(d5),R(d3)
94*dd68e9e8SFrançois Revol	orl	R(d3),R(d1)
95*dd68e9e8SFrançois Revol	movel	R(d1),MEM_PREDEC(res_ptr)
96*dd68e9e8SFrançois Revol	lsll	R(cnt),R(d2)
97*dd68e9e8SFrançois RevolL(L1:)
98*dd68e9e8SFrançois Revol	movel	MEM_PREDEC(s_ptr),R(d1)
99*dd68e9e8SFrançois Revol	movel	R(d1),R(d3)
100*dd68e9e8SFrançois Revol	lsrl	R(d5),R(d3)
101*dd68e9e8SFrançois Revol	orl	R(d3),R(d2)
102*dd68e9e8SFrançois Revol	movel	R(d2),MEM_PREDEC(res_ptr)
103*dd68e9e8SFrançois Revol	lsll	R(cnt),R(d1)
104*dd68e9e8SFrançois Revol
105*dd68e9e8SFrançois Revol	dbf	R(s_size),L(Loop)
106*dd68e9e8SFrançois Revol	subl	#0x10000,R(s_size)
107*dd68e9e8SFrançois Revol	bcc	L(Loop)
108*dd68e9e8SFrançois Revol
109*dd68e9e8SFrançois RevolL(Lend:)
110*dd68e9e8SFrançois Revol	movel	R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */
111*dd68e9e8SFrançois Revol
112*dd68e9e8SFrançois Revol/* Restore used registers from stack frame.  */
113*dd68e9e8SFrançois Revol	moveml	MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
114*dd68e9e8SFrançois Revol	rts
115*dd68e9e8SFrançois Revol
116*dd68e9e8SFrançois Revol/* We loop from least significant end of the arrays, which is only
117*dd68e9e8SFrançois Revol   permissible if the source and destination don't overlap, since the
118*dd68e9e8SFrançois Revol   function is documented to work for overlapping source and destination.  */
119*dd68e9e8SFrançois Revol
120*dd68e9e8SFrançois RevolL(Lspecial:)
121*dd68e9e8SFrançois Revol	clrl	R(d0)			/* initialize carry */
122*dd68e9e8SFrançois Revol	eorw	#1,R(s_size)
123*dd68e9e8SFrançois Revol	lsrl	#1,R(s_size)
124*dd68e9e8SFrançois Revol	bcc	L(LL1)
125*dd68e9e8SFrançois Revol	subql	#1,R(s_size)
126*dd68e9e8SFrançois Revol
127*dd68e9e8SFrançois RevolL(LLoop:)
128*dd68e9e8SFrançois Revol	movel	MEM_POSTINC(s_ptr),R(d2)
129*dd68e9e8SFrançois Revol	addxl	R(d2),R(d2)
130*dd68e9e8SFrançois Revol	movel	R(d2),MEM_POSTINC(res_ptr)
131*dd68e9e8SFrançois RevolL(LL1:)
132*dd68e9e8SFrançois Revol	movel	MEM_POSTINC(s_ptr),R(d2)
133*dd68e9e8SFrançois Revol	addxl	R(d2),R(d2)
134*dd68e9e8SFrançois Revol	movel	R(d2),MEM_POSTINC(res_ptr)
135*dd68e9e8SFrançois Revol
136*dd68e9e8SFrançois Revol	dbf	R(s_size),L(LLoop)
137*dd68e9e8SFrançois Revol	addxl	R(d0),R(d0)		/* save cy in lsb */
138*dd68e9e8SFrançois Revol	subl	#0x10000,R(s_size)
139*dd68e9e8SFrançois Revol	bcs	L(LLend)
140*dd68e9e8SFrançois Revol	lsrl	#1,R(d0)		/* restore cy */
141*dd68e9e8SFrançois Revol	bra	L(LLoop)
142*dd68e9e8SFrançois Revol
143*dd68e9e8SFrançois RevolL(LLend:)
144*dd68e9e8SFrançois Revol/* Restore used registers from stack frame.  */
145*dd68e9e8SFrançois Revol	moveml	MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
146*dd68e9e8SFrançois Revol	rts
147*dd68e9e8SFrançois RevolEND(__mpn_lshift)
148