2.9
[glibc/nacl-glibc.git] / sysdeps / i386 / i586 / lshift.S
blobbc73ee6f3cd9a264feea41ae2bc8b71afa42d7e2
1 /* Pentium optimized __mpn_lshift --
2    Copyright (C) 1992,94,95,96,97,98,2000,2005 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include "sysdep.h"
21 #include "asm-syntax.h"
22 #include "bp-sym.h"
23 #include "bp-asm.h"
25 #define PARMS   LINKAGE+16              /* space for 4 saved regs */
26 #define RES     PARMS
27 #define S       RES+PTR_SIZE
28 #define SIZE    S+PTR_SIZE
29 #define CNT     SIZE+4
31         .text
32 ENTRY (BP_SYM (__mpn_lshift))
33         ENTER
35         pushl   %edi
36         cfi_adjust_cfa_offset (4)
37         pushl   %esi
38         cfi_adjust_cfa_offset (4)
39         pushl   %ebp
40         cfi_adjust_cfa_offset (4)
41         cfi_rel_offset (ebp, 0)
42         pushl   %ebx
43         cfi_adjust_cfa_offset (4)
45         movl    RES(%esp),%edi
46         cfi_rel_offset (edi, 12)
47         movl    S(%esp),%esi
48         cfi_rel_offset (esi, 8)
49         movl    SIZE(%esp),%ebx
50         cfi_rel_offset (ebx, 0)
51         movl    CNT(%esp),%ecx
52 #if __BOUNDED_POINTERS__
53         shll    $2, %ebx                /* convert limbs to bytes */
54         CHECK_BOUNDS_BOTH_WIDE (%edi, RES(%esp), %ebx)
55         CHECK_BOUNDS_BOTH_WIDE (%esi, S(%esp), %ebx)
56         shrl    $2, %ebx
57 #endif
59 /* We can use faster code for shift-by-1 under certain conditions.  */
60         cmp     $1,%ecx
61         jne     L(normal)
62         leal    4(%esi),%eax
63         cmpl    %edi,%eax
64         jnc     L(special)              /* jump if s_ptr + 1 >= res_ptr */
65         leal    (%esi,%ebx,4),%eax
66         cmpl    %eax,%edi
67         jnc     L(special)              /* jump if res_ptr >= s_ptr + size */
69 L(normal):
70         leal    -4(%edi,%ebx,4),%edi
71         leal    -4(%esi,%ebx,4),%esi
73         movl    (%esi),%edx
74         subl    $4,%esi
75         xorl    %eax,%eax
76         shldl   %cl,%edx,%eax           /* compute carry limb */
77         pushl   %eax                    /* push carry limb onto stack */
78         cfi_adjust_cfa_offset (4)
80         decl    %ebx
81         pushl   %ebx
82         cfi_adjust_cfa_offset (4)
83         shrl    $3,%ebx
84         jz      L(end)
86         movl    (%edi),%eax             /* fetch destination cache line */
88         ALIGN   (2)
89 L(oop): movl    -28(%edi),%eax          /* fetch destination cache line */
90         movl    %edx,%ebp
92         movl    (%esi),%eax
93         movl    -4(%esi),%edx
94         shldl   %cl,%eax,%ebp
95         shldl   %cl,%edx,%eax
96         movl    %ebp,(%edi)
97         movl    %eax,-4(%edi)
99         movl    -8(%esi),%ebp
100         movl    -12(%esi),%eax
101         shldl   %cl,%ebp,%edx
102         shldl   %cl,%eax,%ebp
103         movl    %edx,-8(%edi)
104         movl    %ebp,-12(%edi)
106         movl    -16(%esi),%edx
107         movl    -20(%esi),%ebp
108         shldl   %cl,%edx,%eax
109         shldl   %cl,%ebp,%edx
110         movl    %eax,-16(%edi)
111         movl    %edx,-20(%edi)
113         movl    -24(%esi),%eax
114         movl    -28(%esi),%edx
115         shldl   %cl,%eax,%ebp
116         shldl   %cl,%edx,%eax
117         movl    %ebp,-24(%edi)
118         movl    %eax,-28(%edi)
120         subl    $32,%esi
121         subl    $32,%edi
122         decl    %ebx
123         jnz     L(oop)
125 L(end): popl    %ebx
126         cfi_adjust_cfa_offset (-4)
127         andl    $7,%ebx
128         jz      L(end2)
129 L(oop2):
130         movl    (%esi),%eax
131         shldl   %cl,%eax,%edx
132         movl    %edx,(%edi)
133         movl    %eax,%edx
134         subl    $4,%esi
135         subl    $4,%edi
136         decl    %ebx
137         jnz     L(oop2)
139 L(end2):
140         shll    %cl,%edx                /* compute least significant limb */
141         movl    %edx,(%edi)             /* store it */
143         popl    %eax                    /* pop carry limb */
144         cfi_adjust_cfa_offset (-4)
146         popl    %ebx
147         cfi_adjust_cfa_offset (-4)
148         cfi_restore (ebx)
149         popl    %ebp
150         cfi_adjust_cfa_offset (-4)
151         cfi_restore (ebp)
152         popl    %esi
153         cfi_adjust_cfa_offset (-4)
154         cfi_restore (esi)
155         popl    %edi
156         cfi_adjust_cfa_offset (-4)
157         cfi_restore (edi)
159         LEAVE
160         ret
162 /* We loop from least significant end of the arrays, which is only
163    permissible if the source and destination don't overlap, since the
164    function is documented to work for overlapping source and destination.
167         cfi_adjust_cfa_offset (16)
168         cfi_rel_offset (edi, 12)
169         cfi_rel_offset (esi, 8)
170         cfi_rel_offset (ebp, 4)
171         cfi_rel_offset (ebx, 0)
172 L(special):
173         movl    (%esi),%edx
174         addl    $4,%esi
176         decl    %ebx
177         pushl   %ebx
178         cfi_adjust_cfa_offset (4)
179         shrl    $3,%ebx
181         addl    %edx,%edx
182         incl    %ebx
183         decl    %ebx
184         jz      L(Lend)
186         movl    (%edi),%eax             /* fetch destination cache line */
188         ALIGN   (2)
189 L(Loop):
190         movl    28(%edi),%eax           /* fetch destination cache line */
191         movl    %edx,%ebp
193         movl    (%esi),%eax
194         movl    4(%esi),%edx
195         adcl    %eax,%eax
196         movl    %ebp,(%edi)
197         adcl    %edx,%edx
198         movl    %eax,4(%edi)
200         movl    8(%esi),%ebp
201         movl    12(%esi),%eax
202         adcl    %ebp,%ebp
203         movl    %edx,8(%edi)
204         adcl    %eax,%eax
205         movl    %ebp,12(%edi)
207         movl    16(%esi),%edx
208         movl    20(%esi),%ebp
209         adcl    %edx,%edx
210         movl    %eax,16(%edi)
211         adcl    %ebp,%ebp
212         movl    %edx,20(%edi)
214         movl    24(%esi),%eax
215         movl    28(%esi),%edx
216         adcl    %eax,%eax
217         movl    %ebp,24(%edi)
218         adcl    %edx,%edx
219         movl    %eax,28(%edi)
221         leal    32(%esi),%esi           /* use leal not to clobber carry */
222         leal    32(%edi),%edi
223         decl    %ebx
224         jnz     L(Loop)
226 L(Lend):
227         popl    %ebx
228         cfi_adjust_cfa_offset (-4)
229         sbbl    %eax,%eax               /* save carry in %eax */
230         andl    $7,%ebx
231         jz      L(Lend2)
232         addl    %eax,%eax               /* restore carry from eax */
233 L(Loop2):
234         movl    %edx,%ebp
235         movl    (%esi),%edx
236         adcl    %edx,%edx
237         movl    %ebp,(%edi)
239         leal    4(%esi),%esi            /* use leal not to clobber carry */
240         leal    4(%edi),%edi
241         decl    %ebx
242         jnz     L(Loop2)
244         jmp     L(L1)
245 L(Lend2):
246         addl    %eax,%eax               /* restore carry from eax */
247 L(L1):  movl    %edx,(%edi)             /* store last limb */
249         sbbl    %eax,%eax
250         negl    %eax
252         popl    %ebx
253         cfi_adjust_cfa_offset (-4)
254         cfi_restore (ebx)
255         popl    %ebp
256         cfi_adjust_cfa_offset (-4)
257         cfi_restore (ebp)
258         popl    %esi
259         cfi_adjust_cfa_offset (-4)
260         cfi_restore (esi)
261         popl    %edi
262         cfi_adjust_cfa_offset (-4)
263         cfi_restore (edi)
265         LEAVE
266         ret
267 END (BP_SYM (__mpn_lshift))