1/* i80586   lshift
2 *
3 *      Copyright (C) 1992, 1994, 1998,
4 *                    2001, 2002 Free Software Foundation, Inc.
5 *
6 * This file is part of Libgcrypt.
7 *
8 * Libgcrypt is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * Libgcrypt is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 *
22 * Note: This code is heavily based on the GNU MP Library.
23 *	 Actually it's the same code with only minor changes in the
24 *	 way the data is stored; this is to support the abstraction
25 *	 of an optional secure memory allocation which may be used
26 *	 to avoid revealing of sensitive data due to paging etc.
27 */
28
29
30#include "sysdep.h"
31#include "asm-syntax.h"
32
33
34/*******************
35 * mpi_limb_t
36 * _gcry_mpih_lshift( mpi_ptr_t wp,	(sp + 4)
37 *		   mpi_ptr_t up,	(sp + 8)
38 *		   mpi_size_t usize,	(sp + 12)
39 *		   unsigned cnt)	(sp + 16)
40 */
41
42.text
43	ALIGN (3)
44	.globl C_SYMBOL_NAME(_gcry_mpih_lshift)
45C_SYMBOL_NAME(_gcry_mpih_lshift:)
46
47	pushl	%edi
48	pushl	%esi
49	pushl	%ebx
50	pushl	%ebp
51
52	movl	20(%esp),%edi		/* res_ptr */
53	movl	24(%esp),%esi		/* s_ptr */
54	movl	28(%esp),%ebp		/* size */
55	movl	32(%esp),%ecx		/* cnt */
56
57/* We can use faster code for shift-by-1 under certain conditions.  */
58	cmp	$1,%ecx
59	jne	Lnormal
60	leal	4(%esi),%eax
61	cmpl	%edi,%eax
62	jnc	Lspecial		/* jump if s_ptr + 1 >= res_ptr */
63	leal	(%esi,%ebp,4),%eax
64	cmpl	%eax,%edi
65	jnc	Lspecial		/* jump if res_ptr >= s_ptr + size */
66
67Lnormal:
68	leal	-4(%edi,%ebp,4),%edi
69	leal	-4(%esi,%ebp,4),%esi
70
71	movl	(%esi),%edx
72	subl	$4,%esi
73	xorl	%eax,%eax
74	shldl	%cl,%edx,%eax		/* compute carry limb */
75	pushl	%eax			/* push carry limb onto stack */
76
77	decl	%ebp
78	pushl	%ebp
79	shrl	$3,%ebp
80	jz	Lend
81
82	movl	(%edi),%eax		/* fetch destination cache line */
83
84	ALIGN	(2)
85Loop:	movl	-28(%edi),%eax		/* fetch destination cache line */
86	movl	%edx,%ebx
87
88	movl	(%esi),%eax
89	movl	-4(%esi),%edx
90	shldl	%cl,%eax,%ebx
91	shldl	%cl,%edx,%eax
92	movl	%ebx,(%edi)
93	movl	%eax,-4(%edi)
94
95	movl	-8(%esi),%ebx
96	movl	-12(%esi),%eax
97	shldl	%cl,%ebx,%edx
98	shldl	%cl,%eax,%ebx
99	movl	%edx,-8(%edi)
100	movl	%ebx,-12(%edi)
101
102	movl	-16(%esi),%edx
103	movl	-20(%esi),%ebx
104	shldl	%cl,%edx,%eax
105	shldl	%cl,%ebx,%edx
106	movl	%eax,-16(%edi)
107	movl	%edx,-20(%edi)
108
109	movl	-24(%esi),%eax
110	movl	-28(%esi),%edx
111	shldl	%cl,%eax,%ebx
112	shldl	%cl,%edx,%eax
113	movl	%ebx,-24(%edi)
114	movl	%eax,-28(%edi)
115
116	subl	$32,%esi
117	subl	$32,%edi
118	decl	%ebp
119	jnz	Loop
120
121Lend:	popl	%ebp
122	andl	$7,%ebp
123	jz	Lend2
124Loop2:	movl	(%esi),%eax
125	shldl	%cl,%eax,%edx
126	movl	%edx,(%edi)
127	movl	%eax,%edx
128	subl	$4,%esi
129	subl	$4,%edi
130	decl	%ebp
131	jnz	Loop2
132
133Lend2:	shll	%cl,%edx		/* compute least significant limb */
134	movl	%edx,(%edi)		/* store it */
135
136	popl	%eax			/* pop carry limb */
137
138	popl	%ebp
139	popl	%ebx
140	popl	%esi
141	popl	%edi
142	ret
143
144/* We loop from least significant end of the arrays, which is only
145   permissable if the source and destination don't overlap, since the
146   function is documented to work for overlapping source and destination.
147*/
148
149Lspecial:
150	movl	(%esi),%edx
151	addl	$4,%esi
152
153	decl	%ebp
154	pushl	%ebp
155	shrl	$3,%ebp
156
157	addl	%edx,%edx
158	incl	%ebp
159	decl	%ebp
160	jz	LLend
161
162	movl	(%edi),%eax		/* fetch destination cache line */
163
164	ALIGN	(2)
165LLoop:	movl	28(%edi),%eax		/* fetch destination cache line */
166	movl	%edx,%ebx
167
168	movl	(%esi),%eax
169	movl	4(%esi),%edx
170	adcl	%eax,%eax
171	movl	%ebx,(%edi)
172	adcl	%edx,%edx
173	movl	%eax,4(%edi)
174
175	movl	8(%esi),%ebx
176	movl	12(%esi),%eax
177	adcl	%ebx,%ebx
178	movl	%edx,8(%edi)
179	adcl	%eax,%eax
180	movl	%ebx,12(%edi)
181
182	movl	16(%esi),%edx
183	movl	20(%esi),%ebx
184	adcl	%edx,%edx
185	movl	%eax,16(%edi)
186	adcl	%ebx,%ebx
187	movl	%edx,20(%edi)
188
189	movl	24(%esi),%eax
190	movl	28(%esi),%edx
191	adcl	%eax,%eax
192	movl	%ebx,24(%edi)
193	adcl	%edx,%edx
194	movl	%eax,28(%edi)
195
196	leal	32(%esi),%esi		/* use leal not to clobber carry */
197	leal	32(%edi),%edi
198	decl	%ebp
199	jnz	LLoop
200
201LLend:	popl	%ebp
202	sbbl	%eax,%eax		/* save carry in %eax */
203	andl	$7,%ebp
204	jz	LLend2
205	addl	%eax,%eax		/* restore carry from eax */
206LLoop2: movl	%edx,%ebx
207	movl	(%esi),%edx
208	adcl	%edx,%edx
209	movl	%ebx,(%edi)
210
211	leal	4(%esi),%esi		/* use leal not to clobber carry */
212	leal	4(%edi),%edi
213	decl	%ebp
214	jnz	LLoop2
215
216	jmp	LL1
217LLend2: addl	%eax,%eax		/* restore carry from eax */
218LL1:	movl	%edx,(%edi)		/* store last limb */
219
220	sbbl	%eax,%eax
221	negl	%eax
222
223	popl	%ebp
224	popl	%ebx
225	popl	%esi
226	popl	%edi
227	ret
228
229
230