xref: /netbsd-src/external/lgpl3/gmp/dist/mpn/m68k/lshift.asm (revision ce54336801cf28877c3414aa2fcb251dddd543a2)
1dnl  mc68020 mpn_lshift -- mpn left shift.
2
3dnl  Copyright 1996, 1999-2003 Free Software Foundation, Inc.
4
5dnl  This file is part of the GNU MP Library.
6dnl
7dnl  The GNU MP Library is free software; you can redistribute it and/or modify
8dnl  it under the terms of either:
9dnl
10dnl    * the GNU Lesser General Public License as published by the Free
11dnl      Software Foundation; either version 3 of the License, or (at your
12dnl      option) any later version.
13dnl
14dnl  or
15dnl
16dnl    * the GNU General Public License as published by the Free Software
17dnl      Foundation; either version 2 of the License, or (at your option) any
18dnl      later version.
19dnl
20dnl  or both in parallel, as here.
21dnl
22dnl  The GNU MP Library is distributed in the hope that it will be useful, but
23dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25dnl  for more details.
26dnl
27dnl  You should have received copies of the GNU General Public License and the
28dnl  GNU Lesser General Public License along with the GNU MP Library.  If not,
29dnl  see https://www.gnu.org/licenses/.
30
31include(`../config.m4')
32
33
34C           cycles/limb
35C        shift==1  shift>1
36C 68040:    5         12
37
38
39C mp_limb_t mpn_lshift (mp_ptr res_ptr, mp_srcptr s_ptr, mp_size_t s_size,
40C                       unsigned cnt);
41C
42C The "cnt" parameter is either 16 bits or 32 bits depending on
43C SIZEOF_UNSIGNED (see ABI notes in mpn/m68k/README).  The value is of
44C course only 1 to 31.  When loaded as 16 bits there's garbage in the upper
45C half, hence the use of cmpw.  The shift instructions take the their count
46C modulo 64, so the upper part doesn't matter to them either.
47C
48
49C INPUT PARAMETERS
50C res_ptr	(sp + 4)
51C s_ptr		(sp + 8)
52C s_size	(sp + 12)
53C cnt		(sp + 16)
54
55define(res_ptr, `a1')
56define(s_ptr,   `a0')
57define(s_size,  `d6')
58define(cnt,     `d4')
59
60ifdef(`SIZEOF_UNSIGNED',,
61`m4_error(`SIZEOF_UNSIGNED not defined, should be in config.m4
62')')
63
64PROLOGUE(mpn_lshift)
65C Save used registers on the stack.
66	moveml	d2-d6/a2, M(-,sp)
67
68C Copy the arguments to registers.
69	movel	M(sp,28), res_ptr
70	movel	M(sp,32), s_ptr
71	movel	M(sp,36), s_size
72ifelse(SIZEOF_UNSIGNED,2,
73`	movew	M(sp,40), cnt',
74`	movel	M(sp,40), cnt')
75
76	moveql	#1, d5
77	cmpw	d5, cnt
78	bne	L(Lnormal)
79	cmpl	s_ptr, res_ptr
80	bls	L(Lspecial)		C jump if s_ptr >= res_ptr
81
82ifelse(scale_available_p,1,`
83	lea	M(s_ptr,s_size,l,4), a2
84',`
85	movel	s_size, d0
86	asll	#2, d0
87	lea	M(s_ptr,d0,l), a2
88')
89	cmpl	res_ptr, a2
90	bls	L(Lspecial)		C jump if res_ptr >= s_ptr + s_size
91
92L(Lnormal):
93	moveql	#32, d5
94	subl	cnt, d5
95
96ifelse(scale_available_p,1,`
97	lea	M(s_ptr,s_size,l,4), s_ptr
98	lea	M(res_ptr,s_size,l,4), res_ptr
99',`
100	movel	s_size, d0
101	asll	#2, d0
102	addl	d0, s_ptr
103	addl	d0, res_ptr
104')
105	movel	M(-,s_ptr), d2
106	movel	d2, d0
107	lsrl	d5, d0		C compute carry limb
108
109	lsll	cnt, d2
110	movel	d2, d1
111	subql	#1, s_size
112	beq	L(Lend)
113	lsrl	#1, s_size
114	bcs	L(L1)
115	subql	#1, s_size
116
117L(Loop):
118	movel	M(-,s_ptr), d2
119	movel	d2, d3
120	lsrl	d5, d3
121	orl	d3, d1
122	movel	d1, M(-,res_ptr)
123	lsll	cnt, d2
124L(L1):
125	movel	M(-,s_ptr), d1
126	movel	d1, d3
127	lsrl	d5, d3
128	orl	d3, d2
129	movel	d2, M(-,res_ptr)
130	lsll	cnt, d1
131
132	dbf	s_size, L(Loop)
133	subl	#0x10000, s_size
134	bcc	L(Loop)
135
136L(Lend):
137	movel	d1, M(-,res_ptr)	C store least significant limb
138
139C Restore used registers from stack frame.
140	moveml	M(sp,+), d2-d6/a2
141	rts
142
143C We loop from least significant end of the arrays, which is only
144C permissable if the source and destination don't overlap, since the
145C function is documented to work for overlapping source and destination.
146
147L(Lspecial):
148	clrl	d0			C initialize carry
149	eorw	#1, s_size
150	lsrl	#1, s_size
151	bcc	L(LL1)
152	subql	#1, s_size
153
154L(LLoop):
155	movel	M(s_ptr,+), d2
156	addxl	d2, d2
157	movel	d2, M(res_ptr,+)
158L(LL1):
159	movel	M(s_ptr,+), d2
160	addxl	d2, d2
161	movel	d2, M(res_ptr,+)
162
163	dbf	s_size, L(LLoop)
164	addxl	d0, d0		C save cy in lsb
165	subl	#0x10000, s_size
166	bcs	L(LLend)
167	lsrl	#1, d0		C restore cy
168	bra	L(LLoop)
169
170L(LLend):
171C Restore used registers from stack frame.
172	moveml	M(sp,+), d2-d6/a2
173	rts
174
175EPILOGUE(mpn_lshift)
176