1/* mc68020 rshift -- Shift right a low-level natural-number integer.
2 *
3 *      Copyright (C) 1996, 1998, 2001, 2002 Free Software Foundation, Inc.
4 *
5 * This file is part of Libgcrypt.
6 *
7 * Libgcrypt is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * Libgcrypt is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 *
21 * Note: This code is heavily based on the GNU MP Library.
22 *	 Actually it's the same code with only minor changes in the
23 *	 way the data is stored; this is to support the abstraction
24 *	 of an optional secure memory allocation which may be used
25 *	 to avoid revealing of sensitive data due to paging etc.
26 */
27
28
29#include "sysdep.h"
30#include "asm-syntax.h"
31
32
33/*******************
34 * mpi_limb_t
35 * _gcry_mpih_rshift( mpi_ptr_t wp,	(sp + 4)
36 *		   mpi_ptr_t up,	(sp + 8)
37 *		   mpi_size_t usize,	(sp + 12)
38 *		   unsigned cnt)	(sp + 16)
39 */
40
41#define res_ptr a1
42#define s_ptr a0
43#define s_size d6
44#define cnt d4
45
46	TEXT
47	ALIGN
48	GLOBL	C_SYMBOL_NAME(_gcry_mpih_rshift)
49
50C_SYMBOL_NAME(_gcry_mpih_rshift:)
51PROLOG(_gcry_mpih_rshift)
52	/* Save used registers on the stack.  */
53	moveml	R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
54
55	/* Copy the arguments to registers.  */
56	movel	MEM_DISP(sp,28),R(res_ptr)
57	movel	MEM_DISP(sp,32),R(s_ptr)
58	movel	MEM_DISP(sp,36),R(s_size)
59	movel	MEM_DISP(sp,40),R(cnt)
60
61	moveql	#1,R(d5)
62	cmpl	R(d5),R(cnt)
63	bne	L(Rnormal)
64	cmpl	R(res_ptr),R(s_ptr)
65	bls	L(Rspecial)		/* jump if res_ptr >= s_ptr */
66#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
67	lea	MEM_INDX1(res_ptr,s_size,l,4),R(a2)
68#else /* not mc68020 */
69	movel	R(s_size),R(d0)
70	asll	#2,R(d0)
71	lea	MEM_INDX(res_ptr,d0,l),R(a2)
72#endif
73	cmpl	R(s_ptr),R(a2)
74	bls	L(Rspecial)		/* jump if s_ptr >= res_ptr + s_size */
75
76L(Rnormal:)
77	moveql	#32,R(d5)
78	subl	R(cnt),R(d5)
79	movel	MEM_POSTINC(s_ptr),R(d2)
80	movel	R(d2),R(d0)
81	lsll	R(d5),R(d0)		/* compute carry limb */
82
83	lsrl	R(cnt),R(d2)
84	movel	R(d2),R(d1)
85	subql	#1,R(s_size)
86	beq	L(Rend)
87	lsrl	#1,R(s_size)
88	bcs	L(R1)
89	subql	#1,R(s_size)
90
91L(Roop:)
92	movel	MEM_POSTINC(s_ptr),R(d2)
93	movel	R(d2),R(d3)
94	lsll	R(d5),R(d3)
95	orl	R(d3),R(d1)
96	movel	R(d1),MEM_POSTINC(res_ptr)
97	lsrl	R(cnt),R(d2)
98L(R1:)
99	movel	MEM_POSTINC(s_ptr),R(d1)
100	movel	R(d1),R(d3)
101	lsll	R(d5),R(d3)
102	orl	R(d3),R(d2)
103	movel	R(d2),MEM_POSTINC(res_ptr)
104	lsrl	R(cnt),R(d1)
105
106	dbf	R(s_size),L(Roop)
107	subl	#0x10000,R(s_size)
108	bcc	L(Roop)
109
110L(Rend:)
111	movel	R(d1),MEM(res_ptr) /* store most significant limb */
112
113/* Restore used registers from stack frame.  */
114	moveml	MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
115	rts
116
117/* We loop from most significant end of the arrays, which is only
118   permissable if the source and destination don't overlap, since the
119   function is documented to work for overlapping source and destination.  */
120
121L(Rspecial:)
122#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
123	lea	MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
124	lea	MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
125#else /* not mc68000 */
126	movel	R(s_size),R(d0)
127	asll	#2,R(d0)
128	addl	R(s_size),R(s_ptr)
129	addl	R(s_size),R(res_ptr)
130#endif
131
132	clrl	R(d0)			/* initialize carry */
133	eorw	#1,R(s_size)
134	lsrl	#1,R(s_size)
135	bcc	L(LR1)
136	subql	#1,R(s_size)
137
138L(LRoop:)
139	movel	MEM_PREDEC(s_ptr),R(d2)
140	roxrl	#1,R(d2)
141	movel	R(d2),MEM_PREDEC(res_ptr)
142L(LR1:)
143	movel	MEM_PREDEC(s_ptr),R(d2)
144	roxrl	#1,R(d2)
145	movel	R(d2),MEM_PREDEC(res_ptr)
146
147	dbf	R(s_size),L(LRoop)
148	roxrl	#1,R(d0)		/* save cy in msb */
149	subl	#0x10000,R(s_size)
150	bcs	L(LRend)
151	addl	R(d0),R(d0)		/* restore cy */
152	bra	L(LRoop)
153
154L(LRend:)
155/* Restore used registers from stack frame.  */
156	moveml	MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
157	rts
158EPILOG(_gcry_mpih_rshift)
159
160
161
162
163