Support AMD Piledriver by bulldozer kernels.
[platform/upstream/openblas.git] / kernel / x86_64 / symv_L_sse2.S
1 /*********************************************************************/
2 /* Copyright 2009, 2010 The University of Texas at Austin.           */
3 /* All rights reserved.                                              */
4 /*                                                                   */
5 /* Redistribution and use in source and binary forms, with or        */
6 /* without modification, are permitted provided that the following   */
7 /* conditions are met:                                               */
8 /*                                                                   */
9 /*   1. Redistributions of source code must retain the above         */
10 /*      copyright notice, this list of conditions and the following  */
11 /*      disclaimer.                                                  */
12 /*                                                                   */
13 /*   2. Redistributions in binary form must reproduce the above      */
14 /*      copyright notice, this list of conditions and the following  */
15 /*      disclaimer in the documentation and/or other materials       */
16 /*      provided with the distribution.                              */
17 /*                                                                   */
18 /*    THIS  SOFTWARE IS PROVIDED  BY THE  UNIVERSITY OF  TEXAS AT    */
19 /*    AUSTIN  ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,    */
20 /*    INCLUDING, BUT  NOT LIMITED  TO, THE IMPLIED  WARRANTIES OF    */
21 /*    MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR  PURPOSE ARE    */
22 /*    DISCLAIMED.  IN  NO EVENT SHALL THE UNIVERSITY  OF TEXAS AT    */
23 /*    AUSTIN OR CONTRIBUTORS BE  LIABLE FOR ANY DIRECT, INDIRECT,    */
24 /*    INCIDENTAL,  SPECIAL, EXEMPLARY,  OR  CONSEQUENTIAL DAMAGES    */
25 /*    (INCLUDING, BUT  NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE    */
26 /*    GOODS  OR  SERVICES; LOSS  OF  USE,  DATA,  OR PROFITS;  OR    */
27 /*    BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON ANY THEORY OF    */
28 /*    LIABILITY, WHETHER  IN CONTRACT, STRICT  LIABILITY, OR TORT    */
29 /*    (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT    */
30 /*    OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF ADVISED  OF  THE    */
31 /*    POSSIBILITY OF SUCH DAMAGE.                                    */
32 /*                                                                   */
33 /* The views and conclusions contained in the software and           */
34 /* documentation are those of the authors and should not be          */
35 /* interpreted as representing official policies, either expressed   */
36 /* or implied, of The University of Texas at Austin.                 */
37 /*********************************************************************/
38
39 #define ASSEMBLER
40 #include "common.h"
41
42 #ifdef ATOM
43 #define PREFETCH        prefetcht0
44 #define PREFETCHW       prefetcht0
45 #define PREFETCHSIZE    (16 * 12)
46 #endif
47
48 #ifdef CORE2
49 #define PREFETCH        prefetcht0
50 #define PREFETCHW       prefetcht0
51 #define PREFETCHSIZE    (16 * 12)
52 #endif
53
54 #if defined(PENRYN) || defined(DUNNINGTON)
55 #define PREFETCH        prefetcht0
56 #define PREFETCHW       prefetcht0
57 #define PREFETCHSIZE    (16 * 12)
58 #endif
59
60 #if defined(NEHALEM) || defined(SANDYBRIDGE)
61 #define PREFETCH        prefetcht0
62 #define PREFETCHW       prefetcht0
63 #define PREFETCHSIZE    (16 * 12)
64 #endif
65
66 #ifdef PENTIUM4
67 #define PREFETCH        prefetcht0
68 #define PREFETCHW       prefetcht0
69 #define PREFETCHSIZE    (16 * 20)
70 #endif
71
72 #ifdef OPTERON
73 #define PREFETCH        prefetch
74 #define PREFETCHW       prefetchw
75 #define PREFETCHSIZE    (16 * 8)
76 #define movsd           movlpd
77 #endif
78
79 #if defined(BARCELONA) || defined(SHANGHAI) || defined(BOBCAT) || defined(BARCELONA_OPTIMIZATION)
80 #define PREFETCH        prefetch
81 #define PREFETCHW       prefetchw
82 #define PREFETCHSIZE    (16 * 16)
83 #endif
84
85 #ifdef NANO
86 #define PREFETCH        prefetcht0
87 #define PREFETCHW       prefetcht0
88 #define PREFETCHSIZE    (8 * 24)
89 #endif
90
91 #ifdef GENERIC
92 #define PREFETCH        prefetcht0
93 #define PREFETCHW       prefetcht0
94 #define PREFETCHSIZE    (16 * 20)
95 #endif
96
97 #ifndef WINDOWS_ABI
98
99 #define STACKSIZE       80
100         
101 #define OLD_Y            8 + STACKSIZE(%rsp)
102 #define OLD_INCY        16 + STACKSIZE(%rsp)
103 #define OLD_BUFFER      24 + STACKSIZE(%rsp)
104
105 #define M         ARG1
106 #define N         ARG2
107 #define A         ARG3
108 #define LDA       ARG4  
109 #define X         ARG5
110 #define INCX      ARG6  
111
112 #else
113
114 #define STACKSIZE       256
115         
116 #define OLD_LDA          40 + STACKSIZE(%rsp)
117 #define OLD_X            48 + STACKSIZE(%rsp)
118 #define OLD_INCX         56 + STACKSIZE(%rsp)
119 #define OLD_Y            64 + STACKSIZE(%rsp)
120 #define OLD_INCY         72 + STACKSIZE(%rsp)
121 #define OLD_BUFFER       80 + STACKSIZE(%rsp)
122
123 #define M         ARG1
124 #define N         ARG2
125 #define A         ARG4
126 #define LDA       ARG3
127 #define X         %rdi
128 #define INCX      %rsi
129
130 #endif
131
132 #define Y       %r10
133 #define INCY    %r11
134 #define BUFFER  %r12
135
136 #define TEMP    %rax
137 #define I       %rax
138 #define A1      %rbx
139 #define A2      %rbp
140 #define XX      %r13
141 #define YY      %r14
142 #define IS      %r15
143 #define NEW_X   BUFFER
144 #define NEW_Y   X
145
146 #define ALPHA  %xmm0
147
148 #define xtemp1 %xmm0
149 #define xtemp2 %xmm1
150 #define yy1    %xmm2
151 #define yy2    %xmm3
152
153 #define atemp1 %xmm4
154 #define atemp2 %xmm5
155 #define atemp3 %xmm6
156 #define atemp4 %xmm7
157
158 #define xsum1  %xmm8
159 #define xsum2  %xmm9
160 #define xsum3  %xmm10
161 #define xsum4  %xmm11
162
163 #define a1     %xmm12
164 #define a2     %xmm13
165 #define a3     %xmm14
166 #define xt1    %xmm15
167
168         PROLOGUE
169         PROFCODE
170
171         subq    $STACKSIZE, %rsp
172         movq    %rbx,  0(%rsp)
173         movq    %rbp,  8(%rsp)
174         movq    %r12, 16(%rsp)
175         movq    %r13, 24(%rsp)
176         movq    %r14, 32(%rsp)
177         movq    %r15, 40(%rsp)
178
179 #ifdef WINDOWS_ABI
180         movq    %rdi,    48(%rsp)
181         movq    %rsi,    56(%rsp)
182         movups  %xmm6,   64(%rsp)
183         movups  %xmm7,   80(%rsp)
184         movups  %xmm8,   96(%rsp)
185         movups  %xmm9,  112(%rsp)
186         movups  %xmm10, 128(%rsp)
187         movups  %xmm11, 144(%rsp)
188         movups  %xmm12, 160(%rsp)
189         movups  %xmm13, 176(%rsp)
190         movups  %xmm14, 192(%rsp)
191         movups  %xmm15, 208(%rsp)
192
193         movq    OLD_LDA,   LDA
194         movq    OLD_X,     X
195         movq    OLD_INCX,  INCX
196
197         movaps  %xmm2, %xmm0
198 #endif
199
200         movq    OLD_Y,     Y
201         movq    OLD_INCY,   INCY
202         movq    OLD_BUFFER, BUFFER
203
204         leaq    (,INCX, SIZE), INCX
205         leaq    (,INCY, SIZE), INCY
206         leaq    (,LDA,  SIZE), LDA
207
208         testq   M, M
209         jle     .L999
210
211         unpcklpd ALPHA, ALPHA
212
213         movq    BUFFER, XX
214
215         movq    M,  %rax
216         sarq    $3, %rax
217         jle     .L02
218         ALIGN_3
219
220 .L01:
221         movsd   0 * SIZE(X), %xmm1
222         addq    INCX, X
223         movhpd  0 * SIZE(X), %xmm1
224         addq    INCX, X
225         movsd   0 * SIZE(X), %xmm2
226         addq    INCX, X
227         movhpd  0 * SIZE(X), %xmm2
228         addq    INCX, X
229         movsd   0 * SIZE(X), %xmm3
230         addq    INCX, X
231         movhpd  0 * SIZE(X), %xmm3
232         addq    INCX, X
233         movsd   0 * SIZE(X), %xmm4
234         addq    INCX, X
235         movhpd  0 * SIZE(X), %xmm4
236         addq    INCX, X
237
238         mulpd   ALPHA, %xmm1
239         mulpd   ALPHA, %xmm2
240         mulpd   ALPHA, %xmm3
241         mulpd   ALPHA, %xmm4
242
243         movapd  %xmm1, 0 * SIZE(XX)
244         movapd  %xmm2, 2 * SIZE(XX)
245         movapd  %xmm3, 4 * SIZE(XX)
246         movapd  %xmm4, 6 * SIZE(XX)
247
248         addq    $8 * SIZE, XX
249         decq    %rax
250         jg      .L01
251         ALIGN_3
252
253 .L02:
254         movq    M, %rax
255         andq    $7, %rax
256         jle     .L05
257         ALIGN_3
258
259 .L03:
260         movsd   0 * SIZE(X), %xmm1
261         addq    INCX, X
262
263         mulsd   ALPHA, %xmm1
264
265         movlpd  %xmm1, 0 * SIZE(XX)
266
267         addq    $1 * SIZE, XX
268         decq    %rax
269         jg      .L03
270         ALIGN_3
271
272 .L05:
273         /* now we don't need original X */
274         movq   Y, NEW_Y
275
276         addq   $512, XX
277         andq   $-512, XX
278
279         cmpq   $SIZE, INCY
280         je    .L10
281
282         movq   Y,  YY
283         movq   XX, NEW_Y
284
285         movq    M,  %rax
286         sarq    $3, %rax
287         jle     .L07
288         ALIGN_3
289
290 .L06:
291         movsd   0 * SIZE(YY), %xmm0
292         addq    INCY, YY
293         movhpd  0 * SIZE(YY), %xmm0
294         addq    INCY, YY
295         movsd   0 * SIZE(YY), %xmm1
296         addq    INCY, YY
297         movhpd  0 * SIZE(YY), %xmm1
298         addq    INCY, YY
299         movsd   0 * SIZE(YY), %xmm2
300         addq    INCY, YY
301         movhpd  0 * SIZE(YY), %xmm2
302         addq    INCY, YY
303         movsd   0 * SIZE(YY), %xmm3
304         addq    INCY, YY
305         movhpd  0 * SIZE(YY), %xmm3
306         addq    INCY, YY
307
308         movapd  %xmm0, 0 * SIZE(XX)
309         movapd  %xmm1, 2 * SIZE(XX)
310         movapd  %xmm2, 4 * SIZE(XX)
311         movapd  %xmm3, 6 * SIZE(XX)
312
313         addq    $8 * SIZE, XX
314         decq    %rax
315         jg      .L06
316         ALIGN_3
317
318 .L07:
319         movq    M, %rax
320         andq    $7, %rax
321         jle     .L10
322         ALIGN_3
323
324 .L08:
325         movsd   0 * SIZE(YY), %xmm0
326         addq    INCY, YY
327
328         movsd   %xmm0, 0 * SIZE(XX)
329
330         addq    $1 * SIZE, XX
331         decq    %rax
332         jg      .L08
333         ALIGN_3
334
335 .L10:
336         xorq    IS, IS          # is = 0
337
338         cmpq    $4, N
339         jl      .L20
340         ALIGN_3
341
342 .L11:
343         movq    A,  A1
344         leaq    (A, LDA, 2), A2
345         leaq    4 * SIZE(A, LDA, 4), A
346
347         leaq            (NEW_X, IS, SIZE), XX
348         leaq    4 * SIZE(NEW_Y, IS, SIZE), YY
349
350         movapd          0 * SIZE(XX), atemp2
351         movapd          2 * SIZE(XX), atemp4
352
353         movsd    0 * SIZE(A1), xsum1
354         movhpd   1 * SIZE(A1), xsum1
355         mulpd    atemp2, xsum1
356
357         movsd    1 * SIZE(A1), xsum2
358         movhpd   1 * SIZE(A1, LDA, 1), xsum2
359         mulpd    atemp2, xsum2
360
361         movsd    2 * SIZE(A1), xsum3
362         movhpd   2 * SIZE(A1, LDA, 1), xsum3
363         mulpd    atemp2, xsum3
364
365         movsd    3 * SIZE(A1), xsum4
366         movhpd   3 * SIZE(A1, LDA, 1), xsum4
367         mulpd    atemp2, xsum4
368
369         movsd    2 * SIZE(A1), a1
370         movhpd   3 * SIZE(A1), a1
371         mulpd    atemp4, a1
372         addpd    a1, xsum1
373
374         movsd    2 * SIZE(A1, LDA, 1), a1
375         movhpd   3 * SIZE(A1, LDA, 1), a1
376         mulpd    atemp4, a1
377         addpd    a1, xsum2
378
379         movsd    2 * SIZE(A2), a1
380         movhpd   3 * SIZE(A2), a1
381         mulpd    atemp4, a1
382         addpd    a1, xsum3
383
384         movsd    3 * SIZE(A2), a1
385         movhpd   3 * SIZE(A2, LDA, 1), a1
386         mulpd    atemp4, a1
387         addpd    a1, xsum4
388
389         movapd   4 * SIZE(XX), xtemp1
390         movapd   6 * SIZE(XX), xtemp2
391
392         movsd    4 * SIZE(A1), a1
393         movhpd   5 * SIZE(A1), a1
394         movsd    6 * SIZE(A1), a2
395         movhpd   7 * SIZE(A1), a2
396         movsd    4 * SIZE(A1, LDA, 1), a3
397         movhpd   5 * SIZE(A1, LDA, 1), a3
398
399         movsd    0 * SIZE(YY), yy1
400         movhpd   1 * SIZE(YY), yy1
401         movsd    2 * SIZE(YY), yy2
402         movhpd   3 * SIZE(YY), yy2
403
404 #ifndef HAVE_SSE3
405         movapd   atemp2, atemp1
406         unpcklpd atemp1, atemp1
407         unpckhpd atemp2, atemp2
408         movapd   atemp4, atemp3
409         unpcklpd atemp3, atemp3
410         unpckhpd atemp4, atemp4
411 #else
412         movddup  atemp2, atemp1
413         unpckhpd atemp2, atemp2
414         movddup  atemp4, atemp3
415         unpckhpd atemp4, atemp4
416 #endif
417
418         addq     $4 * SIZE, XX
419         addq     $4 * SIZE, A1
420         addq     $4 * SIZE, A2
421
422         movq    M,  I
423         subq    IS, I
424         subq    $4, I
425         sarq    $3, I
426         jle     .L15
427         ALIGN_3
428
429 .L12:
430         movapd   xtemp1, xt1
431         mulpd    a1,     xt1
432         mulpd    atemp1, a1
433         addpd    xt1,    xsum1
434         addpd    a1,     yy1
435         movsd    2 * SIZE(A1, LDA, 1), a1
436         movhpd   3 * SIZE(A1, LDA, 1), a1
437
438         PREFETCH        PREFETCHSIZE(A1)
439
440         movapd   xtemp2, xt1
441         mulpd    a2,     xt1
442         mulpd    atemp1, a2
443         addpd    xt1,    xsum1
444         addpd    a2,     yy2
445         movsd    0 * SIZE(A2), a2
446         movhpd   1 * SIZE(A2), a2
447
448         movapd   xtemp1, xt1
449         mulpd    a3,     xt1
450         mulpd    atemp2, a3
451         addpd    xt1,    xsum2
452         addpd    a3,     yy1
453         movsd    2 * SIZE(A2), a3
454         movhpd   3 * SIZE(A2), a3
455
456 #if !defined(CORE2) && !defined(PENRYN) && !defined(DUNNINGTON)
457         PREFETCH        PREFETCHSIZE(XX)
458 #endif
459
460         movapd   xtemp2, xt1
461         mulpd    a1,     xt1
462         mulpd    atemp2, a1
463         addpd    xt1,    xsum2
464         addpd    a1,     yy2
465         movsd    0 * SIZE(A2, LDA, 1), a1
466         movhpd   1 * SIZE(A2, LDA, 1), a1
467
468         movapd   xtemp1, xt1
469         mulpd    a2,     xt1
470         mulpd    atemp3, a2
471         addpd    xt1,    xsum3
472         addpd    a2,     yy1
473         movsd    2 * SIZE(A2, LDA, 1), a2
474         movhpd   3 * SIZE(A2, LDA, 1), a2
475
476         PREFETCH        PREFETCHSIZE(A1, LDA, 1)
477
478         movapd   xtemp2, xt1
479         mulpd    a3,     xt1
480         mulpd    atemp3, a3
481         addpd    xt1,    xsum3
482         addpd    a3,     yy2
483         movsd    4 * SIZE(A1), a3
484         movhpd   5 * SIZE(A1), a3
485
486         movapd   xtemp1, xt1
487         movapd   4 * SIZE(XX), xtemp1
488         mulpd    a1,     xt1
489         mulpd    atemp4, a1
490         addpd    xt1,    xsum4
491         addpd    a1,     yy1
492         movsd    6 * SIZE(A1), a1
493         movhpd   7 * SIZE(A1), a1
494
495         movapd   xtemp2, xt1
496         movapd   6 * SIZE(XX), xtemp2
497         mulpd    a2,     xt1
498         mulpd    atemp4, a2
499         addpd    xt1,    xsum4
500         addpd    a2,     yy2
501         movsd    4 * SIZE(A1, LDA, 1), a2
502         movhpd   5 * SIZE(A1, LDA, 1), a2
503
504         movsd    yy1, 0 * SIZE(YY)
505         movhpd   yy1, 1 * SIZE(YY)
506         movsd    4 * SIZE(YY), yy1
507         movhpd   5 * SIZE(YY), yy1
508
509         movsd    yy2, 2 * SIZE(YY)
510         movhpd   yy2, 3 * SIZE(YY)
511         movsd    6 * SIZE(YY), yy2
512         movhpd   7 * SIZE(YY), yy2
513
514         movapd   xtemp1, xt1
515         mulpd    a3,     xt1
516         mulpd    atemp1, a3
517         addpd    xt1,    xsum1
518         addpd    a3,     yy1
519         movsd    6 * SIZE(A1, LDA, 1), a3
520         movhpd   7 * SIZE(A1, LDA, 1), a3
521
522         PREFETCH        PREFETCHSIZE(A2)
523
524         movapd   xtemp2, xt1
525         mulpd    a1,     xt1
526         mulpd    atemp1, a1
527         addpd    xt1,    xsum1
528         addpd    a1,     yy2
529         movsd    4 * SIZE(A2), a1
530         movhpd   5 * SIZE(A2), a1
531
532         movapd   xtemp1, xt1
533         mulpd    a2,     xt1
534         mulpd    atemp2, a2
535         addpd    xt1,    xsum2
536         addpd    a2,     yy1
537         movsd    6 * SIZE(A2), a2
538         movhpd   7 * SIZE(A2), a2
539
540 #if !defined(CORE2) && !defined(PENRYN) && !defined(DUNNINGTON)
541         PREFETCHW       PREFETCHSIZE(YY)
542 #endif
543
544         movapd   xtemp2, xt1
545         mulpd    a3,     xt1
546         mulpd    atemp2, a3
547         addpd    xt1,    xsum2
548         addpd    a3,     yy2
549         movsd    4 * SIZE(A2, LDA, 1), a3
550         movhpd   5 * SIZE(A2, LDA, 1), a3
551
552         movapd   xtemp1, xt1
553         mulpd    a1,     xt1
554         mulpd    atemp3, a1
555         addpd    xt1,    xsum3
556         addpd    a1,     yy1
557         movsd    6 * SIZE(A2, LDA, 1), a1
558         movhpd   7 * SIZE(A2, LDA, 1), a1
559
560         PREFETCH        PREFETCHSIZE(A2, LDA, 1)
561
562         movapd   xtemp2, xt1
563         mulpd    a2,     xt1
564         mulpd    atemp3, a2
565         addpd    xt1,    xsum3
566         addpd    a2,     yy2
567         movsd   10 * SIZE(A1), a2
568         movhpd  11 * SIZE(A1), a2
569
570         movapd   xtemp1, xt1
571         movapd   8 * SIZE(XX), xtemp1
572         mulpd    a3,     xt1
573         mulpd    atemp4, a3
574         addpd    xt1,    xsum4
575         addpd    a3,     yy1
576         movsd    8 * SIZE(A1, LDA, 1), a3
577         movhpd   9 * SIZE(A1, LDA, 1), a3
578
579         movapd   xtemp2, xt1
580         movapd  10 * SIZE(XX), xtemp2
581         mulpd    a1,     xt1
582         mulpd    atemp4, a1
583         addpd    xt1,    xsum4
584         addpd    a1,     yy2
585         movsd    8 * SIZE(A1), a1
586         movhpd   9 * SIZE(A1), a1
587
588         movsd    yy1, 4 * SIZE(YY)
589         movhpd   yy1, 5 * SIZE(YY)
590         movsd    8 * SIZE(YY), yy1
591         movhpd   9 * SIZE(YY), yy1
592
593         movsd    yy2, 6 * SIZE(YY)
594         movhpd   yy2, 7 * SIZE(YY)
595         movsd   10 * SIZE(YY), yy2
596         movhpd  11 * SIZE(YY), yy2
597
598         addq     $8 * SIZE, XX
599         addq     $8 * SIZE, YY
600         addq     $8 * SIZE, A1
601         addq     $8 * SIZE, A2
602
603         decq     I
604         jg       .L12
605         ALIGN_3
606
607 .L15:
608         movq    M,  I
609         subq    IS, I
610         subq    $4, I
611         test    $4, I
612         jle     .L17
613
614         movapd   xtemp1, xt1
615         mulpd    a1,     xt1
616         mulpd    atemp1, a1
617         addpd    xt1,    xsum1
618         addpd    a1,     yy1
619         movsd    2 * SIZE(A1, LDA, 1), a1
620         movhpd   3 * SIZE(A1, LDA, 1), a1
621
622         movapd   xtemp2, xt1
623         mulpd    a2,     xt1
624         mulpd    atemp1, a2
625         addpd    xt1,    xsum1
626         addpd    a2,     yy2
627         movsd    0 * SIZE(A2), a2
628         movhpd   1 * SIZE(A2), a2
629
630         movapd   xtemp1, xt1
631         mulpd    a3,     xt1
632         mulpd    atemp2, a3
633         addpd    xt1,    xsum2
634         addpd    a3,     yy1
635         movsd    2 * SIZE(A2), a3
636         movhpd   3 * SIZE(A2), a3
637
638         movapd   xtemp2, xt1
639         mulpd    a1,     xt1
640         mulpd    atemp2, a1
641         addpd    xt1,    xsum2
642         addpd    a1,     yy2
643         movsd    0 * SIZE(A2, LDA, 1), a1
644         movhpd   1 * SIZE(A2, LDA, 1), a1
645
646         movapd   xtemp1, xt1
647         mulpd    a2,     xt1
648         mulpd    atemp3, a2
649         addpd    xt1,    xsum3
650         addpd    a2,     yy1
651         movsd    2 * SIZE(A2, LDA, 1), a2
652         movhpd   3 * SIZE(A2, LDA, 1), a2
653
654         movapd   xtemp2, xt1
655         mulpd    a3,     xt1
656         mulpd    atemp3, a3
657         addpd    xt1,    xsum3
658         addpd    a3,     yy2
659         movsd    4 * SIZE(A1, LDA, 1), a3
660         movhpd   5 * SIZE(A1, LDA, 1), a3
661
662         movapd   xtemp1, xt1
663         movapd   4 * SIZE(XX), xtemp1
664         mulpd    a1,     xt1
665         mulpd    atemp4, a1
666         addpd    xt1,    xsum4
667         addpd    a1,     yy1
668         movsd    4 * SIZE(A1), a1
669         movhpd   5 * SIZE(A1), a1
670
671         movapd   xtemp2, xt1
672         movapd   6 * SIZE(XX), xtemp2
673         mulpd    a2,     xt1
674         mulpd    atemp4, a2
675         addpd    xt1,    xsum4
676         addpd    a2,     yy2
677         movsd    6 * SIZE(A1), a2
678         movhpd   7 * SIZE(A1), a2
679
680         movsd    yy1, 0 * SIZE(YY)
681         movhpd   yy1, 1 * SIZE(YY)
682         movsd    4 * SIZE(YY), yy1
683         movhpd   5 * SIZE(YY), yy1
684
685         movsd    yy2, 2 * SIZE(YY)
686         movhpd   yy2, 3 * SIZE(YY)
687         movsd    6 * SIZE(YY), yy2
688         movhpd   7 * SIZE(YY), yy2
689
690         addq     $4 * SIZE, XX
691         addq     $4 * SIZE, YY
692         addq     $4 * SIZE, A1
693         addq     $4 * SIZE, A2
694         ALIGN_3
695
696 .L17:
697         testq   $2, M
698         jle     .L18
699
700         movapd   xtemp1, xt1
701         mulpd    a1,     xt1
702         mulpd    atemp1, a1
703         addpd    xt1,    xsum1
704         addpd    a1,     yy1
705         movsd    0 * SIZE(A1, LDA, 1), a1
706         movhpd   1 * SIZE(A1, LDA, 1), a1
707
708         movapd   xtemp1, xt1
709         mulpd    a1,     xt1
710         mulpd    atemp2, a1
711         addpd    xt1,    xsum2
712         addpd    a1,     yy1
713         movsd    0 * SIZE(A2), a1
714         movhpd   1 * SIZE(A2), a1
715
716         movapd   xtemp1, xt1
717         mulpd    a1,     xt1
718         mulpd    atemp3, a1
719         addpd    xt1,    xsum3
720         addpd    a1,     yy1
721         movsd    0 * SIZE(A2, LDA, 1), a1
722         movhpd   1 * SIZE(A2, LDA, 1), a1
723
724         movapd   xtemp1, xt1
725         movapd   2 * SIZE(XX), xtemp1
726         mulpd    a1,     xt1
727         mulpd    atemp4, a1
728         addpd    xt1,    xsum4
729         addpd    a1,     yy1
730         movsd    2 * SIZE(A1), a1
731
732         movsd    yy1, 0 * SIZE(YY)
733         movhpd   yy1, 1 * SIZE(YY)
734         movsd    2 * SIZE(YY), yy1
735
736         addq     $2 * SIZE, XX
737         addq     $2 * SIZE, YY
738         addq     $2 * SIZE, A1
739         addq     $2 * SIZE, A2
740         ALIGN_3
741
742 .L18:
743         testq   $1, M
744         jle     .L19
745
746         movapd   xtemp1, xt1
747         mulsd    a1,     xt1
748         mulsd    atemp1, a1
749         addsd    xt1,    xsum1
750         addpd    a1,     yy1
751         movsd    0 * SIZE(A1, LDA, 1), a1
752
753         movapd   xtemp1, xt1
754         mulsd    a1,     xt1
755         mulsd    atemp2, a1
756         addsd    xt1,    xsum2
757         addsd    a1,     yy1
758         movsd    0 * SIZE(A2), a1
759
760         movapd   xtemp1, xt1
761         mulsd    a1,     xt1
762         mulsd    atemp3, a1
763         addsd    xt1,    xsum3
764         addsd    a1,     yy1
765         movsd    0 * SIZE(A2, LDA, 1), a1
766
767         movapd   xtemp1, xt1
768         mulsd    a1,     xt1
769         mulsd    atemp4, a1
770         addsd    xt1,    xsum4
771         addsd    a1,     yy1
772
773         movsd    yy1, 0 * SIZE(YY)
774         ALIGN_3
775
776 .L19:
777 #ifndef HAVE_SSE3
778         movapd  xsum1, atemp1
779         movapd  xsum3, atemp3
780
781         unpcklpd xsum2, xsum1
782         unpcklpd xsum4, xsum3
783
784         unpckhpd xsum2, atemp1
785         unpckhpd xsum4, atemp3
786
787         addpd    atemp1, xsum1
788         addpd    atemp3, xsum3
789 #else
790         haddpd   xsum2, xsum1
791         haddpd   xsum4, xsum3
792 #endif
793
794         movsd    0 * SIZE(NEW_Y, IS, SIZE), yy1
795         movhpd   1 * SIZE(NEW_Y, IS, SIZE), yy1
796         movsd    2 * SIZE(NEW_Y, IS, SIZE), yy2
797         movhpd   3 * SIZE(NEW_Y, IS, SIZE), yy2
798
799         addpd    xsum1, yy1
800         addpd    xsum3, yy2
801
802         movsd    yy1, 0 * SIZE(NEW_Y, IS, SIZE)
803         movhpd   yy1, 1 * SIZE(NEW_Y, IS, SIZE)
804         movsd    yy2, 2 * SIZE(NEW_Y, IS, SIZE)
805         movhpd   yy2, 3 * SIZE(NEW_Y, IS, SIZE)
806
807         addq     $4, IS
808
809         movq     IS, I
810         addq     $4, I
811         cmpq     N, I
812         jle      .L11
813         ALIGN_3
814
815 .L20:
816         testq   $2, N
817         jle     .L30
818
819         movq    A,  A1
820         leaq    2 * SIZE(A, LDA, 2), A
821
822         movapd          0 * SIZE(NEW_X, IS, SIZE), atemp2
823
824         movsd    0 * SIZE(A1), xsum1
825         movhpd   1 * SIZE(A1), xsum1
826         mulpd    atemp2, xsum1
827
828         movsd    1 * SIZE(A1), xsum2
829         movhpd   1 * SIZE(A1, LDA, 1), xsum2
830         mulpd    atemp2, xsum2
831
832 #ifndef HAVE_SSE3
833         movapd   atemp2, atemp1
834         unpcklpd atemp1, atemp1
835 #else
836         movddup  atemp2, atemp1
837 #endif
838         unpckhpd atemp2, atemp2
839
840         testq   $1, M
841         jle     .L29
842
843         movsd    2 * SIZE(A1), a1
844         movsd    2 * SIZE(A1, LDA, 1), a2
845         movsd    2 * SIZE(NEW_X, IS, SIZE), xtemp1
846         movsd    2 * SIZE(NEW_Y, IS, SIZE), yy1
847
848         movapd   xtemp1, xt1
849         mulsd    a1,     xt1
850         mulsd    atemp1, a1
851         addsd    xt1,    xsum1
852         addpd    a1,     yy1
853
854         movapd   xtemp1, xt1
855         mulsd    a2,     xt1
856         mulsd    atemp2, a2
857         addsd    xt1,    xsum2
858         addsd    a2,     yy1
859
860         movsd    yy1, 2 * SIZE(NEW_Y, IS, SIZE)
861         ALIGN_3
862
863 .L29:
864 #ifndef HAVE_SSE3
865         movapd  xsum1, atemp1
866         unpcklpd xsum2, xsum1
867         unpckhpd xsum2, atemp1
868         addpd    atemp1, xsum1
869 #else
870         haddpd   xsum2, xsum1
871 #endif
872
873         movsd    0 * SIZE(NEW_Y, IS, SIZE), yy1
874         movhpd   1 * SIZE(NEW_Y, IS, SIZE), yy1
875
876         addpd    xsum1, yy1
877
878         movsd    yy1, 0 * SIZE(NEW_Y, IS, SIZE)
879         movhpd   yy1, 1 * SIZE(NEW_Y, IS, SIZE)
880
881         addq     $2, IS
882         ALIGN_3
883
884 .L30:
885         testq   $1, N
886         jle     .L990
887
888         movsd    0 * SIZE(A), xsum1
889         movsd    0 * SIZE(NEW_X, IS, SIZE), atemp1
890         movsd    0 * SIZE(NEW_Y, IS, SIZE), yy1
891
892         mulsd    atemp1, xsum1
893         addsd    xsum1, yy1
894         movsd    yy1, 0 * SIZE(NEW_Y, IS, SIZE)
895         ALIGN_3
896
897 .L990:
898         cmpq   $SIZE, INCY
899         je    .L999
900
901         movq    M,  %rax
902         sarq    $3, %rax
903         jle     .L997
904         ALIGN_3
905
906 .L996:
907         movapd   0 * SIZE(NEW_Y), %xmm0
908         movapd   2 * SIZE(NEW_Y), %xmm1
909         movapd   4 * SIZE(NEW_Y), %xmm2
910         movapd   6 * SIZE(NEW_Y), %xmm3
911
912         movsd   %xmm0,  0 * SIZE(Y)
913         addq    INCY, Y
914         movhpd  %xmm0,  0 * SIZE(Y)
915         addq    INCY, Y
916         movsd   %xmm1,  0 * SIZE(Y)
917         addq    INCY, Y
918         movhpd  %xmm1,  0 * SIZE(Y)
919         addq    INCY, Y
920         movsd   %xmm2,  0 * SIZE(Y)
921         addq    INCY, Y
922         movhpd  %xmm2,  0 * SIZE(Y)
923         addq    INCY, Y
924         movsd   %xmm3,  0 * SIZE(Y)
925         addq    INCY, Y
926         movhpd  %xmm3,  0 * SIZE(Y)
927         addq    INCY, Y
928
929         addq    $8 * SIZE, NEW_Y
930         decq    %rax
931         jg      .L996
932         ALIGN_3
933
934 .L997:
935         movq    M, %rax
936         andq    $7, %rax
937         jle     .L999
938         ALIGN_3
939
940 .L998:
941         movsd   0 * SIZE(NEW_Y), %xmm0
942
943         movsd   %xmm0,  0 * SIZE(Y)
944         addq    INCY, Y
945
946         addq    $1 * SIZE, NEW_Y
947
948         decq    %rax
949         jg      .L998
950         ALIGN_3
951
952
953 .L999:
954         movq      0(%rsp), %rbx
955         movq      8(%rsp), %rbp
956         movq     16(%rsp), %r12
957         movq     24(%rsp), %r13
958         movq     32(%rsp), %r14
959         movq     40(%rsp), %r15
960
961 #ifdef WINDOWS_ABI
962         movq     48(%rsp), %rdi
963         movq     56(%rsp), %rsi
964         movups   64(%rsp), %xmm6
965         movups   80(%rsp), %xmm7
966         movups   96(%rsp), %xmm8
967         movups  112(%rsp), %xmm9
968         movups  128(%rsp), %xmm10
969         movups  144(%rsp), %xmm11
970         movups  160(%rsp), %xmm12
971         movups  176(%rsp), %xmm13
972         movups  192(%rsp), %xmm14
973         movups  208(%rsp), %xmm15
974 #endif
975
976         addq    $STACKSIZE, %rsp
977         ret
978         EPILOGUE