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