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
21 #include "asm-syntax.h"
25 #define PARMS LINKAGE+16 /* space for 4 saved regs */
27 #define S RES+PTR_SIZE
28 #define SIZE S+PTR_SIZE
32 ENTRY (BP_SYM (__mpn_lshift))
36 cfi_adjust_cfa_offset (4)
38 cfi_adjust_cfa_offset (4)
40 cfi_adjust_cfa_offset (4)
41 cfi_rel_offset (ebp, 0)
43 cfi_adjust_cfa_offset (4)
46 cfi_rel_offset (edi, 12)
48 cfi_rel_offset (esi, 8)
50 cfi_rel_offset (ebx, 0)
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)
59 /* We can use faster code for shift-by-1 under certain conditions. */
64 jnc L(special) /* jump if s_ptr + 1 >= res_ptr */
65 leal (%esi,%ebx,4),%eax
67 jnc L(special) /* jump if res_ptr >= s_ptr + size */
70 leal -4(%edi,%ebx,4),%edi
71 leal -4(%esi,%ebx,4),%esi
76 shldl %cl,%edx,%eax /* compute carry limb */
77 pushl %eax /* push carry limb onto stack */
78 cfi_adjust_cfa_offset (4)
82 cfi_adjust_cfa_offset (4)
86 movl (%edi),%eax /* fetch destination cache line */
89 L(oop): movl -28(%edi),%eax /* fetch destination cache line */
126 cfi_adjust_cfa_offset (-4)
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)
147 cfi_adjust_cfa_offset (-4)
150 cfi_adjust_cfa_offset (-4)
153 cfi_adjust_cfa_offset (-4)
156 cfi_adjust_cfa_offset (-4)
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)
178 cfi_adjust_cfa_offset (4)
186 movl (%edi),%eax /* fetch destination cache line */
190 movl 28(%edi),%eax /* fetch destination cache line */
221 leal 32(%esi),%esi /* use leal not to clobber carry */
228 cfi_adjust_cfa_offset (-4)
229 sbbl %eax,%eax /* save carry in %eax */
232 addl %eax,%eax /* restore carry from eax */
239 leal 4(%esi),%esi /* use leal not to clobber carry */
246 addl %eax,%eax /* restore carry from eax */
247 L(L1): movl %edx,(%edi) /* store last limb */
253 cfi_adjust_cfa_offset (-4)
256 cfi_adjust_cfa_offset (-4)
259 cfi_adjust_cfa_offset (-4)
262 cfi_adjust_cfa_offset (-4)
267 END (BP_SYM (__mpn_lshift))