remove empty dir
[ghc-hetmet.git] / rts / gmp / mpn / x86 / k6 / k62mmx / lshift.asm
1 dnl  AMD K6-2 mpn_lshift -- mpn left shift.
2 dnl 
3 dnl  K6-2: 1.75 cycles/limb
4
5
6 dnl  Copyright (C) 1999, 2000 Free Software Foundation, Inc.
7 dnl 
8 dnl  This file is part of the GNU MP Library.
9 dnl 
10 dnl  The GNU MP Library is free software; you can redistribute it and/or
11 dnl  modify it under the terms of the GNU Lesser General Public License as
12 dnl  published by the Free Software Foundation; either version 2.1 of the
13 dnl  License, or (at your option) any later version.
14 dnl 
15 dnl  The GNU MP Library is distributed in the hope that it will be useful,
16 dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
17 dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 dnl  Lesser General Public License for more details.
19 dnl 
20 dnl  You should have received a copy of the GNU Lesser General Public
21 dnl  License along with the GNU MP Library; see the file COPYING.LIB.  If
22 dnl  not, write to the Free Software Foundation, Inc., 59 Temple Place -
23 dnl  Suite 330, Boston, MA 02111-1307, USA.
24
25
26 include(`../config.m4')
27
28
29 C mp_limb_t mpn_lshift (mp_ptr dst, mp_srcptr src, mp_size_t size,
30 C                       unsigned shift);
31 C
32
33 defframe(PARAM_SHIFT,16)
34 defframe(PARAM_SIZE, 12)
35 defframe(PARAM_SRC,  8)
36 defframe(PARAM_DST,  4)
37 deflit(`FRAME',0)
38
39 dnl  used after src has been fetched
40 define(VAR_RETVAL,`PARAM_SRC')
41
42 dnl  minimum 9, because unrolled loop can't handle less
43 deflit(UNROLL_THRESHOLD, 9)
44
45         .text
46         ALIGN(32)
47
48 PROLOGUE(mpn_lshift)
49 deflit(`FRAME',0)
50
51         C The 1 limb case can be done without the push %ebx, but it's then
52         C still the same speed.  The push is left as a free helping hand for
53         C the two_or_more code.
54
55         movl    PARAM_SIZE, %eax
56         pushl   %ebx                    FRAME_pushl()
57
58         movl    PARAM_SRC, %ebx
59         decl    %eax
60
61         movl    PARAM_SHIFT, %ecx
62         jnz     L(two_or_more)
63
64         movl    (%ebx), %edx            C src limb
65         movl    PARAM_DST, %ebx
66
67         shldl(  %cl, %edx, %eax)        C return value
68
69         shll    %cl, %edx
70
71         movl    %edx, (%ebx)            C dst limb
72         popl    %ebx
73
74         ret
75
76
77 C -----------------------------------------------------------------------------
78         ALIGN(16)       C avoid offset 0x1f
79 L(two_or_more):
80         C eax   size-1
81         C ebx   src
82         C ecx   shift
83         C edx
84
85         movl    (%ebx,%eax,4), %edx     C src high limb
86         negl    %ecx
87
88         movd    PARAM_SHIFT, %mm6
89         addl    $32, %ecx               C 32-shift
90
91         shrl    %cl, %edx
92         cmpl    $UNROLL_THRESHOLD-1, %eax
93
94         movl    %edx, VAR_RETVAL
95         jae     L(unroll)
96
97
98         movd    %ecx, %mm7
99         movl    %eax, %ecx
100
101         movl    PARAM_DST, %eax
102
103 L(simple):
104         C eax   dst
105         C ebx   src
106         C ecx   counter, size-1 to 1
107         C edx   retval
108         C
109         C mm0   scratch
110         C mm6   shift
111         C mm7   32-shift
112
113         movq    -4(%ebx,%ecx,4), %mm0
114
115         psrlq   %mm7, %mm0
116
117 Zdisp(  movd,   %mm0, 0,(%eax,%ecx,4))
118         loop    L(simple)
119
120
121         movd    (%ebx), %mm0
122         popl    %ebx
123
124         psllq   %mm6, %mm0
125
126         movd    %mm0, (%eax)
127         movl    %edx, %eax
128
129         femms
130         ret
131
132
133 C -----------------------------------------------------------------------------
134         ALIGN(16)
135 L(unroll):
136         C eax   size-1
137         C ebx   src
138         C ecx   32-shift
139         C edx   retval (but instead VAR_RETVAL is used)
140         C
141         C mm6   shift
142
143         addl    $32, %ecx
144         movl    PARAM_DST, %edx
145
146         movd    %ecx, %mm7
147         subl    $7, %eax                        C size-8
148
149         leal    (%edx,%eax,4), %ecx             C alignment of dst
150
151         movq    32-8(%ebx,%eax,4), %mm2         C src high qword
152         testb   $4, %cl
153
154         jz      L(dst_aligned)
155         psllq   %mm6, %mm2
156
157         psrlq   $32, %mm2
158         decl    %eax
159
160         movd    %mm2, 32(%edx,%eax,4)           C dst high limb
161         movq    32-8(%ebx,%eax,4), %mm2         C new src high qword
162 L(dst_aligned):
163
164         movq    32-16(%ebx,%eax,4), %mm0        C src second highest qword
165
166
167         C This loop is the important bit, the rest is just support for it.
168         C Four src limbs are held at the start, and four more will be read.
169         C Four dst limbs will be written.  This schedule seems necessary for
170         C full speed.
171         C
172         C The use of size-8 lets the loop stop when %eax goes negative and
173         C leaves -4 to -1 which can be tested with test $1 and $2.
174
175 L(top):
176         C eax   counter, size-8 step by -4 until <0
177         C ebx   src
178         C ecx
179         C edx   dst
180         C
181         C mm0   src next qword
182         C mm1   scratch
183         C mm2   src prev qword
184         C mm6   shift
185         C mm7   64-shift
186
187         psllq   %mm6, %mm2
188         subl    $4, %eax
189
190         movq    %mm0, %mm1
191         psrlq   %mm7, %mm0
192
193         por     %mm0, %mm2
194         movq    24(%ebx,%eax,4), %mm0
195
196         psllq   %mm6, %mm1
197         movq    %mm2, 40(%edx,%eax,4)
198
199         movq    %mm0, %mm2
200         psrlq   %mm7, %mm0
201
202         por     %mm0, %mm1
203         movq    16(%ebx,%eax,4), %mm0
204
205         movq    %mm1, 32(%edx,%eax,4)
206         jnc     L(top)
207
208
209         C Now have four limbs in mm2 (prev) and mm0 (next), plus eax mod 4.
210         C
211         C 8(%ebx) is the next source, and 24(%edx) is the next destination.
212         C %eax is between -4 and -1, representing respectively 0 to 3 extra
213         C limbs that must be read.
214
215
216         testl   $2, %eax        C testl to avoid bad cache line crossing
217         jz      L(finish_nottwo)
218
219         C Two more limbs: lshift mm2, OR it with rshifted mm0, mm0 becomes
220         C new mm2 and a new mm0 is loaded.
221
222         psllq   %mm6, %mm2
223         movq    %mm0, %mm1
224
225         psrlq   %mm7, %mm0
226         subl    $2, %eax
227
228         por     %mm0, %mm2
229         movq    16(%ebx,%eax,4), %mm0
230
231         movq    %mm2, 32(%edx,%eax,4)
232         movq    %mm1, %mm2
233 L(finish_nottwo):
234
235
236         C lshift mm2, OR with rshifted mm0, mm1 becomes lshifted mm0
237
238         testb   $1, %al
239         psllq   %mm6, %mm2
240
241         movq    %mm0, %mm1
242         psrlq   %mm7, %mm0
243
244         por     %mm0, %mm2
245         psllq   %mm6, %mm1
246
247         movq    %mm2, 24(%edx,%eax,4)
248         jz      L(finish_even)
249
250
251         C Size is odd, so mm1 and one extra limb to process.
252
253         movd    (%ebx), %mm0            C src[0]
254         popl    %ebx
255 deflit(`FRAME',0)
256
257         movq    %mm0, %mm2
258         psllq   $32, %mm0
259
260         psrlq   %mm7, %mm0
261
262         psllq   %mm6, %mm2
263         por     %mm0, %mm1
264
265         movq    %mm1, 4(%edx)           C dst[1,2]
266         movd    %mm2, (%edx)            C dst[0]
267
268         movl    VAR_RETVAL, %eax
269
270         femms
271         ret
272
273
274         nop     C avoid bad cache line crossing
275 L(finish_even):
276 deflit(`FRAME',4)
277         C Size is even, so only mm1 left to process.
278
279         movq    %mm1, (%edx)            C dst[0,1]
280         movl    VAR_RETVAL, %eax
281
282         popl    %ebx
283         femms
284         ret
285
286 EPILOGUE()