import works
[libgcrypt.git] / mpi / m68k / mpih-shift.S
1 /* mc68020 __mpn_lshift -- Shift left a low-level natural-number integer.
2
3 Copyright (C) 1996 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Library General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
15 License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 MA 02111-1307, USA. */
21
22 #include "sysdep.h"
23 #include "asm-syntax.h"
24
25
26 /*******************
27  * mpi_limb_t
28  * mpihelp_lshift( mpi_ptr_t wp,        (sp + 4)
29  *                 mpi_ptr_t up,        (sp + 8)
30  *                 mpi_size_t usize,    (sp + 12)
31  *                 unsigned cnt)        (sp + 16)
32  */
33
34 #define res_ptr a1
35 #define s_ptr a0
36 #define s_size d6
37 #define cnt d4
38
39         TEXT
40         ALIGN
41         GLOBL   C_SYMBOL_NAME(mpihelp_lshift)
42
43 C_SYMBOL_NAME(mpihelp_lshift:)
44 PROLOG(mpihelp_lshift)
45
46         /* Save used registers on the stack.  */
47         moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
48
49         /* Copy the arguments to registers.  */
50         movel   MEM_DISP(sp,28),R(res_ptr)
51         movel   MEM_DISP(sp,32),R(s_ptr)
52         movel   MEM_DISP(sp,36),R(s_size)
53         movel   MEM_DISP(sp,40),R(cnt)
54
55         moveql  #1,R(d5)
56         cmpl    R(d5),R(cnt)
57         bne     L(Lnormal)
58         cmpl    R(s_ptr),R(res_ptr)
59         bls     L(Lspecial)             /* jump if s_ptr >= res_ptr */
60 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
61         lea     MEM_INDX1(s_ptr,s_size,l,4),R(a2)
62 #else /* not mc68020 */
63         movel   R(s_size),R(d0)
64         asll    #2,R(d0)
65         lea     MEM_INDX(s_ptr,d0,l),R(a2)
66 #endif
67         cmpl    R(res_ptr),R(a2)
68         bls     L(Lspecial)             /* jump if res_ptr >= s_ptr + s_size */
69
70 L(Lnormal:)
71         moveql  #32,R(d5)
72         subl    R(cnt),R(d5)
73
74 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
75         lea     MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
76         lea     MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
77 #else /* not mc68000 */
78         movel   R(s_size),R(d0)
79         asll    #2,R(d0)
80         addl    R(s_size),R(s_ptr)
81         addl    R(s_size),R(res_ptr)
82 #endif
83         movel   MEM_PREDEC(s_ptr),R(d2)
84         movel   R(d2),R(d0)
85         lsrl    R(d5),R(d0)             /* compute carry limb */
86
87         lsll    R(cnt),R(d2)
88         movel   R(d2),R(d1)
89         subql   #1,R(s_size)
90         beq     L(Lend)
91         lsrl    #1,R(s_size)
92         bcs     L(L1)
93         subql   #1,R(s_size)
94
95 L(Loop:)
96         movel   MEM_PREDEC(s_ptr),R(d2)
97         movel   R(d2),R(d3)
98         lsrl    R(d5),R(d3)
99         orl     R(d3),R(d1)
100         movel   R(d1),MEM_PREDEC(res_ptr)
101         lsll    R(cnt),R(d2)
102 L(L1:)
103         movel   MEM_PREDEC(s_ptr),R(d1)
104         movel   R(d1),R(d3)
105         lsrl    R(d5),R(d3)
106         orl     R(d3),R(d2)
107         movel   R(d2),MEM_PREDEC(res_ptr)
108         lsll    R(cnt),R(d1)
109
110         dbf     R(s_size),L(Loop)
111         subl    #0x10000,R(s_size)
112         bcc     L(Loop)
113
114 L(Lend:)
115         movel   R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */
116
117 /* Restore used registers from stack frame.  */
118         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
119         rts
120
121 /* We loop from least significant end of the arrays, which is only
122    permissable if the source and destination don't overlap, since the
123    function is documented to work for overlapping source and destination.  */
124
125 L(Lspecial:)
126         clrl    R(d0)                   /* initialize carry */
127         eorw    #1,R(s_size)
128         lsrl    #1,R(s_size)
129         bcc     L(LL1)
130         subql   #1,R(s_size)
131
132 L(LLoop:)
133         movel   MEM_POSTINC(s_ptr),R(d2)
134         addxl   R(d2),R(d2)
135         movel   R(d2),MEM_POSTINC(res_ptr)
136 L(LL1:)
137         movel   MEM_POSTINC(s_ptr),R(d2)
138         addxl   R(d2),R(d2)
139         movel   R(d2),MEM_POSTINC(res_ptr)
140
141         dbf     R(s_size),L(LLoop)
142         addxl   R(d0),R(d0)             /* save cy in lsb */
143         subl    #0x10000,R(s_size)
144         bcs     L(LLend)
145         lsrl    #1,R(d0)                /* restore cy */
146         bra     L(LLoop)
147
148 L(LLend:)
149 /* Restore used registers from stack frame.  */
150         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
151         rts
152 EPILOG(mpihelp_lshift)
153
154
155
156
157 /*******************
158  * mpi_limb_t
159  * mpihelp_rshift( mpi_ptr_t wp,        (sp + 4)
160  *                 mpi_ptr_t up,        (sp + 8)
161  *                 mpi_size_t usize,    (sp + 12)
162  *                 unsigned cnt)        (sp + 16)
163  */
164
165 #define res_ptr a1
166 #define s_ptr a0
167 #define s_size d6
168 #define cnt d4
169
170         TEXT
171         ALIGN
172         GLOBL   C_SYMBOL_NAME(mpihelp_rshift)
173
174 C_SYMBOL_NAME(mpihelp_rshift:)
175 PROLOG(mpihelp_rshift)
176         /* Save used registers on the stack.  */
177         moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
178
179         /* Copy the arguments to registers.  */
180         movel   MEM_DISP(sp,28),R(res_ptr)
181         movel   MEM_DISP(sp,32),R(s_ptr)
182         movel   MEM_DISP(sp,36),R(s_size)
183         movel   MEM_DISP(sp,40),R(cnt)
184
185         moveql  #1,R(d5)
186         cmpl    R(d5),R(cnt)
187         bne     L(Rnormal)
188         cmpl    R(res_ptr),R(s_ptr)
189         bls     L(Lspecial)             /* jump if res_ptr >= s_ptr */
190 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
191         lea     MEM_INDX1(res_ptr,s_size,l,4),R(a2)
192 #else /* not mc68020 */
193         movel   R(s_size),R(d0)
194         asll    #2,R(d0)
195         lea     MEM_INDX(res_ptr,d0,l),R(a2)
196 #endif
197         cmpl    R(s_ptr),R(a2)
198         bls     L(Lspecial)             /* jump if s_ptr >= res_ptr + s_size */
199
200 L(Rnormal:)
201         moveql  #32,R(d5)
202         subl    R(cnt),R(d5)
203         movel   MEM_POSTINC(s_ptr),R(d2)
204         movel   R(d2),R(d0)
205         lsll    R(d5),R(d0)             /* compute carry limb */
206
207         lsrl    R(cnt),R(d2)
208         movel   R(d2),R(d1)
209         subql   #1,R(s_size)
210         beq     L(Rend)
211         lsrl    #1,R(s_size)
212         bcs     L(R1)
213         subql   #1,R(s_size)
214
215 L(Roop:)
216         movel   MEM_POSTINC(s_ptr),R(d2)
217         movel   R(d2),R(d3)
218         lsll    R(d5),R(d3)
219         orl     R(d3),R(d1)
220         movel   R(d1),MEM_POSTINC(res_ptr)
221         lsrl    R(cnt),R(d2)
222 L(R1:)
223         movel   MEM_POSTINC(s_ptr),R(d1)
224         movel   R(d1),R(d3)
225         lsll    R(d5),R(d3)
226         orl     R(d3),R(d2)
227         movel   R(d2),MEM_POSTINC(res_ptr)
228         lsrl    R(cnt),R(d1)
229
230         dbf     R(s_size),L(Roop)
231         subl    #0x10000,R(s_size)
232         bcc     L(Roop)
233
234 L(Rend:)
235         movel   R(d1),MEM(res_ptr) /* store most significant limb */
236
237 /* Restore used registers from stack frame.  */
238         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
239         rts
240
241 /* We loop from most significant end of the arrays, which is only
242    permissable if the source and destination don't overlap, since the
243    function is documented to work for overlapping source and destination.  */
244
245 L(Lspecial:)
246 #if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
247         lea     MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
248         lea     MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
249 #else /* not mc68000 */
250         movel   R(s_size),R(d0)
251         asll    #2,R(d0)
252         addl    R(s_size),R(s_ptr)
253         addl    R(s_size),R(res_ptr)
254 #endif
255
256         clrl    R(d0)                   /* initialize carry */
257         eorw    #1,R(s_size)
258         lsrl    #1,R(s_size)
259         bcc     L(LR1)
260         subql   #1,R(s_size)
261
262 L(LRoop:)
263         movel   MEM_PREDEC(s_ptr),R(d2)
264         roxrl   #1,R(d2)
265         movel   R(d2),MEM_PREDEC(res_ptr)
266 L(LR1:)
267         movel   MEM_PREDEC(s_ptr),R(d2)
268         roxrl   #1,R(d2)
269         movel   R(d2),MEM_PREDEC(res_ptr)
270
271         dbf     R(s_size),L(LRoop)
272         roxrl   #1,R(d0)                /* save cy in msb */
273         subl    #0x10000,R(s_size)
274         bcs     L(LRend)
275         addl    R(d0),R(d0)             /* restore cy */
276         bra     L(LRoop)
277
278 L(LRend:)
279 /* Restore used registers from stack frame.  */
280         moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
281         rts
282 EPILOG(mpihelp_rshift)
283
284
285
286