2.9
[glibc/nacl-glibc.git] / sysdeps / i386 / i586 / rshift.S
blob7b88289d3e1f5eb3547ecb62d3b6fc74642eb41c
1 /* Pentium optimized __mpn_rshift --
2    Copyright (C) 1992,94,95,96,97,98,2000,2005 Free Software Foundation, Inc.
3    This file is part of the GNU MP Library.
5    The GNU MP Library is free software; you can redistribute it and/or modify
6    it under the terms of the GNU Lesser General Public License as published by
7    the Free Software Foundation; either version 2.1 of the License, or (at your
8    option) any later version.
10    The GNU MP Library is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
13    License for more details.
15    You should have received a copy of the GNU Lesser General Public License
16    along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
17    the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18    MA 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_rshift))
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(%edi),%eax
63         cmpl    %esi,%eax
64         jnc     L(special)              /* jump if res_ptr + 1 >= s_ptr */
65         leal    (%edi,%ebx,4),%eax
66         cmpl    %eax,%esi
67         jnc     L(special)              /* jump if s_ptr >= res_ptr + size */
69 L(normal):
70         movl    (%esi),%edx
71         addl    $4,%esi
72         xorl    %eax,%eax
73         shrdl   %cl,%edx,%eax           /* compute carry limb */
74         pushl   %eax                    /* push carry limb onto stack */
75         cfi_adjust_cfa_offset (4)
77         decl    %ebx
78         pushl   %ebx
79         cfi_adjust_cfa_offset (4)
80         shrl    $3,%ebx
81         jz      L(end)
83         movl    (%edi),%eax             /* fetch destination cache line */
85         ALIGN   (2)
86 L(oop): movl    28(%edi),%eax           /* fetch destination cache line */
87         movl    %edx,%ebp
89         movl    (%esi),%eax
90         movl    4(%esi),%edx
91         shrdl   %cl,%eax,%ebp
92         shrdl   %cl,%edx,%eax
93         movl    %ebp,(%edi)
94         movl    %eax,4(%edi)
96         movl    8(%esi),%ebp
97         movl    12(%esi),%eax
98         shrdl   %cl,%ebp,%edx
99         shrdl   %cl,%eax,%ebp
100         movl    %edx,8(%edi)
101         movl    %ebp,12(%edi)
103         movl    16(%esi),%edx
104         movl    20(%esi),%ebp
105         shrdl   %cl,%edx,%eax
106         shrdl   %cl,%ebp,%edx
107         movl    %eax,16(%edi)
108         movl    %edx,20(%edi)
110         movl    24(%esi),%eax
111         movl    28(%esi),%edx
112         shrdl   %cl,%eax,%ebp
113         shrdl   %cl,%edx,%eax
114         movl    %ebp,24(%edi)
115         movl    %eax,28(%edi)
117         addl    $32,%esi
118         addl    $32,%edi
119         decl    %ebx
120         jnz     L(oop)
122 L(end): popl    %ebx
123         cfi_adjust_cfa_offset (-4)
124         andl    $7,%ebx
125         jz      L(end2)
126 L(oop2):
127         movl    (%esi),%eax
128         shrdl   %cl,%eax,%edx           /* compute result limb */
129         movl    %edx,(%edi)
130         movl    %eax,%edx
131         addl    $4,%esi
132         addl    $4,%edi
133         decl    %ebx
134         jnz     L(oop2)
136 L(end2):
137         shrl    %cl,%edx                /* compute most significant limb */
138         movl    %edx,(%edi)             /* store it */
140         popl    %eax                    /* pop carry limb */
141         cfi_adjust_cfa_offset (-4)
143         popl    %ebx
144         cfi_adjust_cfa_offset (-4)
145         cfi_restore (ebx)
146         popl    %ebp
147         cfi_adjust_cfa_offset (-4)
148         cfi_restore (ebp)
149         popl    %esi
150         cfi_adjust_cfa_offset (-4)
151         cfi_restore (esi)
152         popl    %edi
153         cfi_adjust_cfa_offset (-4)
154         cfi_restore (edi)
156         LEAVE
157         ret
159 /* We loop from least significant end of the arrays, which is only
160    permissible if the source and destination don't overlap, since the
161    function is documented to work for overlapping source and destination.
164         cfi_adjust_cfa_offset (16)
165         cfi_rel_offset (edi, 12)
166         cfi_rel_offset (esi, 8)
167         cfi_rel_offset (ebp, 4)
168         cfi_rel_offset (ebx, 0)
169 L(special):
170         leal    -4(%edi,%ebx,4),%edi
171         leal    -4(%esi,%ebx,4),%esi
173         movl    (%esi),%edx
174         subl    $4,%esi
176         decl    %ebx
177         pushl   %ebx
178         cfi_adjust_cfa_offset (4)
179         shrl    $3,%ebx
181         shrl    $1,%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         rcrl    $1,%eax
196         movl    %ebp,(%edi)
197         rcrl    $1,%edx
198         movl    %eax,-4(%edi)
200         movl    -8(%esi),%ebp
201         movl    -12(%esi),%eax
202         rcrl    $1,%ebp
203         movl    %edx,-8(%edi)
204         rcrl    $1,%eax
205         movl    %ebp,-12(%edi)
207         movl    -16(%esi),%edx
208         movl    -20(%esi),%ebp
209         rcrl    $1,%edx
210         movl    %eax,-16(%edi)
211         rcrl    $1,%ebp
212         movl    %edx,-20(%edi)
214         movl    -24(%esi),%eax
215         movl    -28(%esi),%edx
216         rcrl    $1,%eax
217         movl    %ebp,-24(%edi)
218         rcrl    $1,%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         rcrl    $1,%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         movl    $0,%eax
250         rcrl    $1,%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_rshift))