bec72b016874de3bd2c27d501f1b67dae38a287e
[platform/upstream/glibc.git] / sysdeps / i386 / i586 / rshift.S
1 /* Pentium optimized __mpn_rshift --
2    Copyright (C) 1992-2013 Free Software Foundation, Inc.
3    This file is part of the GNU MP Library.
4
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.
9
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.
14
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,
17    see <http://www.gnu.org/licenses/>.  */
18
19 #include "sysdep.h"
20 #include "asm-syntax.h"
21 #include "bp-sym.h"
22 #include "bp-asm.h"
23
24 #define PARMS   LINKAGE+16              /* space for 4 saved regs */
25 #define RES     PARMS
26 #define S       RES+PTR_SIZE
27 #define SIZE    S+PTR_SIZE
28 #define CNT     SIZE+4
29
30         .text
31 ENTRY (BP_SYM (__mpn_rshift))
32
33         pushl   %edi
34         cfi_adjust_cfa_offset (4)
35         pushl   %esi
36         cfi_adjust_cfa_offset (4)
37         pushl   %ebp
38         cfi_adjust_cfa_offset (4)
39         cfi_rel_offset (ebp, 0)
40         pushl   %ebx
41         cfi_adjust_cfa_offset (4)
42
43         movl    RES(%esp),%edi
44         cfi_rel_offset (edi, 12)
45         movl    S(%esp),%esi
46         cfi_rel_offset (esi, 8)
47         movl    SIZE(%esp),%ebx
48         cfi_rel_offset (ebx, 0)
49         movl    CNT(%esp),%ecx
50
51 /* We can use faster code for shift-by-1 under certain conditions.  */
52         cmp     $1,%ecx
53         jne     L(normal)
54         leal    4(%edi),%eax
55         cmpl    %esi,%eax
56         jnc     L(special)              /* jump if res_ptr + 1 >= s_ptr */
57         leal    (%edi,%ebx,4),%eax
58         cmpl    %eax,%esi
59         jnc     L(special)              /* jump if s_ptr >= res_ptr + size */
60
61 L(normal):
62         movl    (%esi),%edx
63         addl    $4,%esi
64         xorl    %eax,%eax
65         shrdl   %cl,%edx,%eax           /* compute carry limb */
66         pushl   %eax                    /* push carry limb onto stack */
67         cfi_adjust_cfa_offset (4)
68
69         decl    %ebx
70         pushl   %ebx
71         cfi_adjust_cfa_offset (4)
72         shrl    $3,%ebx
73         jz      L(end)
74
75         movl    (%edi),%eax             /* fetch destination cache line */
76
77         ALIGN   (2)
78 L(oop): movl    28(%edi),%eax           /* fetch destination cache line */
79         movl    %edx,%ebp
80
81         movl    (%esi),%eax
82         movl    4(%esi),%edx
83         shrdl   %cl,%eax,%ebp
84         shrdl   %cl,%edx,%eax
85         movl    %ebp,(%edi)
86         movl    %eax,4(%edi)
87
88         movl    8(%esi),%ebp
89         movl    12(%esi),%eax
90         shrdl   %cl,%ebp,%edx
91         shrdl   %cl,%eax,%ebp
92         movl    %edx,8(%edi)
93         movl    %ebp,12(%edi)
94
95         movl    16(%esi),%edx
96         movl    20(%esi),%ebp
97         shrdl   %cl,%edx,%eax
98         shrdl   %cl,%ebp,%edx
99         movl    %eax,16(%edi)
100         movl    %edx,20(%edi)
101
102         movl    24(%esi),%eax
103         movl    28(%esi),%edx
104         shrdl   %cl,%eax,%ebp
105         shrdl   %cl,%edx,%eax
106         movl    %ebp,24(%edi)
107         movl    %eax,28(%edi)
108
109         addl    $32,%esi
110         addl    $32,%edi
111         decl    %ebx
112         jnz     L(oop)
113
114 L(end): popl    %ebx
115         cfi_adjust_cfa_offset (-4)
116         andl    $7,%ebx
117         jz      L(end2)
118 L(oop2):
119         movl    (%esi),%eax
120         shrdl   %cl,%eax,%edx           /* compute result limb */
121         movl    %edx,(%edi)
122         movl    %eax,%edx
123         addl    $4,%esi
124         addl    $4,%edi
125         decl    %ebx
126         jnz     L(oop2)
127
128 L(end2):
129         shrl    %cl,%edx                /* compute most significant limb */
130         movl    %edx,(%edi)             /* store it */
131
132         popl    %eax                    /* pop carry limb */
133         cfi_adjust_cfa_offset (-4)
134
135         popl    %ebx
136         cfi_adjust_cfa_offset (-4)
137         cfi_restore (ebx)
138         popl    %ebp
139         cfi_adjust_cfa_offset (-4)
140         cfi_restore (ebp)
141         popl    %esi
142         cfi_adjust_cfa_offset (-4)
143         cfi_restore (esi)
144         popl    %edi
145         cfi_adjust_cfa_offset (-4)
146         cfi_restore (edi)
147
148         ret
149
150 /* We loop from least significant end of the arrays, which is only
151    permissible if the source and destination don't overlap, since the
152    function is documented to work for overlapping source and destination.
153 */
154
155         cfi_adjust_cfa_offset (16)
156         cfi_rel_offset (edi, 12)
157         cfi_rel_offset (esi, 8)
158         cfi_rel_offset (ebp, 4)
159         cfi_rel_offset (ebx, 0)
160 L(special):
161         leal    -4(%edi,%ebx,4),%edi
162         leal    -4(%esi,%ebx,4),%esi
163
164         movl    (%esi),%edx
165         subl    $4,%esi
166
167         decl    %ebx
168         pushl   %ebx
169         cfi_adjust_cfa_offset (4)
170         shrl    $3,%ebx
171
172         shrl    $1,%edx
173         incl    %ebx
174         decl    %ebx
175         jz      L(Lend)
176
177         movl    (%edi),%eax             /* fetch destination cache line */
178
179         ALIGN   (2)
180 L(Loop):
181         movl    -28(%edi),%eax          /* fetch destination cache line */
182         movl    %edx,%ebp
183
184         movl    (%esi),%eax
185         movl    -4(%esi),%edx
186         rcrl    $1,%eax
187         movl    %ebp,(%edi)
188         rcrl    $1,%edx
189         movl    %eax,-4(%edi)
190
191         movl    -8(%esi),%ebp
192         movl    -12(%esi),%eax
193         rcrl    $1,%ebp
194         movl    %edx,-8(%edi)
195         rcrl    $1,%eax
196         movl    %ebp,-12(%edi)
197
198         movl    -16(%esi),%edx
199         movl    -20(%esi),%ebp
200         rcrl    $1,%edx
201         movl    %eax,-16(%edi)
202         rcrl    $1,%ebp
203         movl    %edx,-20(%edi)
204
205         movl    -24(%esi),%eax
206         movl    -28(%esi),%edx
207         rcrl    $1,%eax
208         movl    %ebp,-24(%edi)
209         rcrl    $1,%edx
210         movl    %eax,-28(%edi)
211
212         leal    -32(%esi),%esi          /* use leal not to clobber carry */
213         leal    -32(%edi),%edi
214         decl    %ebx
215         jnz     L(Loop)
216
217 L(Lend):
218         popl    %ebx
219         cfi_adjust_cfa_offset (-4)
220         sbbl    %eax,%eax               /* save carry in %eax */
221         andl    $7,%ebx
222         jz      L(Lend2)
223         addl    %eax,%eax               /* restore carry from eax */
224 L(Loop2):
225         movl    %edx,%ebp
226         movl    (%esi),%edx
227         rcrl    $1,%edx
228         movl    %ebp,(%edi)
229
230         leal    -4(%esi),%esi           /* use leal not to clobber carry */
231         leal    -4(%edi),%edi
232         decl    %ebx
233         jnz     L(Loop2)
234
235         jmp     L(L1)
236 L(Lend2):
237         addl    %eax,%eax               /* restore carry from eax */
238 L(L1):  movl    %edx,(%edi)             /* store last limb */
239
240         movl    $0,%eax
241         rcrl    $1,%eax
242
243         popl    %ebx
244         cfi_adjust_cfa_offset (-4)
245         cfi_restore (ebx)
246         popl    %ebp
247         cfi_adjust_cfa_offset (-4)
248         cfi_restore (ebp)
249         popl    %esi
250         cfi_adjust_cfa_offset (-4)
251         cfi_restore (esi)
252         popl    %edi
253         cfi_adjust_cfa_offset (-4)
254         cfi_restore (edi)
255
256         ret
257 END (BP_SYM (__mpn_rshift))