Merge branch 'develop' into develop_arm_softfp
[platform/upstream/openblas.git] / kernel / arm / zgemv_n_vfp.S
1 /***************************************************************************
2 Copyright (c) 2013, The OpenBLAS Project
3 All rights reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 1. Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 2. Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13 3. Neither the name of the OpenBLAS project nor the names of
14 its contributors may be used to endorse or promote products
15 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBLAS PROJECT OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *****************************************************************************/
27
28 /**************************************************************************************
29 * 2013/11/29 Saar
30 *        BLASTEST               : OK
31 *        CTEST                  : OK
32 *        TEST                   : OK
33 *
34 **************************************************************************************/
35
36 #define ASSEMBLER
37 #include "common.h"
38
39 #define STACKSIZE 256
40
41 #if !defined(__ARM_PCS_VFP)
42 #define OLD_ALPHAR      [fp, #0 ]
43 #define OLD_ALPHAI      [fp, #8 ]
44 #define OLD_A_SOFTFP    [fp, #16]
45 #define OLD_LDA         [fp, #20]
46 #define X               [fp, #24]
47 #define OLD_INC_X       [fp, #28]
48 #define Y               [fp, #32]
49 #define OLD_INC_Y       [fp, #36]
50 #else
51 #define OLD_LDA         [fp, #0 ]
52 #define X               [fp, #4 ]
53 #define OLD_INC_X       [fp, #8 ]
54 #define Y               [fp, #12 ]
55 #define OLD_INC_Y       [fp, #16 ]
56 #endif
57
58 #define OLD_A           r3
59 #define OLD_M           r0
60
61 #define AO1     r0
62 #define N       r1
63 #define J       r2
64
65 #define AO2     r4
66 #define XO      r5
67 #define YO      r6
68 #define LDA     r7
69 #define INC_X   r8
70 #define INC_Y   r9
71
72 #define I       r12
73
74 #define FP_ZERO [fp, #-228]
75 #define FP_ZERO_0 [fp, #-228]
76 #define FP_ZERO_1 [fp, #-224]
77
78
79 #define ALPHA_I [fp, #-236]
80 #define ALPHA_R [fp, #-244]
81
82 #define M       [fp, #-252 ]
83 #define A       [fp, #-256 ]
84
85
86 #define X_PRE   64
87 #define Y_PRE   0
88 #define A_PRE   0
89
90 /**************************************************************************************/
91
92 #if !defined(CONJ) && !defined(XCONJ)
93
94         #define KMAC_R  fnmacd
95         #define KMAC_I  fmacd
96
97         #define FMAC_R1 fmacd
98         #define FMAC_R2 fnmacd
99         #define FMAC_I1 fmacd
100         #define FMAC_I2 fmacd
101
102 #elif defined(CONJ) && !defined(XCONJ)
103
104         #define KMAC_R  fmacd
105         #define KMAC_I  fnmacd
106
107         #define FMAC_R1 fmacd
108         #define FMAC_R2 fnmacd
109         #define FMAC_I1 fmacd
110         #define FMAC_I2 fmacd
111
112 #elif !defined(CONJ) && defined(XCONJ)
113
114         #define KMAC_R  fmacd
115         #define KMAC_I  fnmacd
116
117         #define FMAC_R1 fmacd
118         #define FMAC_R2 fmacd
119         #define FMAC_I1 fnmacd
120         #define FMAC_I2 fmacd
121
122 #else
123
124         #define KMAC_R  fnmacd
125         #define KMAC_I  fmacd
126
127         #define FMAC_R1 fmacd
128         #define FMAC_R2 fmacd
129         #define FMAC_I1 fnmacd
130         #define FMAC_I2 fmacd
131
132 #endif
133
134 .macro INIT_F4
135
136         pld     [ YO, #Y_PRE ]
137         fldd                    d8, FP_ZERO
138         vmov.f64                d9 , d8
139         vmov.f64                d10, d8
140         vmov.f64                d11, d8
141         vmov.f64                d12, d8
142         vmov.f64                d13, d8
143         vmov.f64                d14, d8
144         vmov.f64                d15, d8
145
146 .endm
147
148 .macro KERNEL_F4X4
149
150         pld     [ XO, #X_PRE ]
151         KERNEL_F4X1
152         KERNEL_F4X1
153         pld     [ XO, #X_PRE ]
154         KERNEL_F4X1
155         KERNEL_F4X1
156
157 .endm
158
159 .macro KERNEL_F4X1
160
161         fldd    d0 , [ AO1 ]
162
163         fldd    d4 , [ XO ]
164         fldd    d5 , [ XO, #8 ]
165
166         pld     [ AO2, #A_PRE ]
167
168         fldd    d1 , [ AO1, #8  ]
169         fmacd   d8  , d0,  d4
170         fldd    d2 , [ AO1, #16 ]
171         fmacd   d9  , d0,  d5
172         fldd    d3 , [ AO1, #24 ]
173         fmacd   d10 , d2,  d4
174         fldd    d0 , [ AO1, #32 ]
175         fmacd   d11 , d2,  d5
176
177         KMAC_R  d8  , d1,  d5
178         KMAC_I  d9  , d1,  d4
179         KMAC_R  d10 , d3,  d5
180         fldd    d1 , [ AO1, #40 ]
181         KMAC_I  d11 , d3,  d4
182
183         fldd    d2 , [ AO1, #48 ]
184
185         fmacd   d12 , d0,  d4
186         fldd    d3 , [ AO1, #56 ]
187         fmacd   d13 , d0,  d5
188         pld     [ AO2, #A_PRE+32 ]
189         fmacd   d14 , d2,  d4
190         fmacd   d15 , d2,  d5
191
192         KMAC_R  d12 , d1,  d5
193         add     XO , XO, #16
194         KMAC_I  d13 , d1,  d4
195         add     AO1 , AO1, LDA
196         KMAC_R  d14 , d3,  d5
197         add     AO2 , AO2, LDA
198         KMAC_I  d15 , d3,  d4
199
200 .endm
201
202 .macro SAVE_F4
203
204         fldd            d0, ALPHA_R
205         fldd            d1, ALPHA_I
206
207         fldmiad YO, { d4 - d7 }
208
209         FMAC_R1 d4 , d0 , d8
210         FMAC_I1 d5 , d0 , d9
211         FMAC_R2 d4 , d1 , d9
212         FMAC_I2 d5 , d1 , d8
213
214         FMAC_R1 d6 , d0 , d10
215         FMAC_I1 d7 , d0 , d11
216         FMAC_R2 d6 , d1 , d11
217         FMAC_I2 d7 , d1 , d10
218
219         fstmiad YO!, { d4 - d7 }
220
221         fldmiad YO, { d4 - d7 }
222
223         FMAC_R1 d4 , d0 , d12
224         FMAC_I1 d5 , d0 , d13
225         FMAC_R2 d4 , d1 , d13
226         FMAC_I2 d5 , d1 , d12
227
228         FMAC_R1 d6 , d0 , d14
229         FMAC_I1 d7 , d0 , d15
230         FMAC_R2 d6 , d1 , d15
231         FMAC_I2 d7 , d1 , d14
232
233         fstmiad YO!, { d4 - d7 }
234
235 .endm
236
237
238
239
240 .macro INIT_F1
241
242         fldd                    d8, FP_ZERO
243         vmov.f64                d9 , d8
244
245 .endm
246
247 .macro KERNEL_F1X1
248
249         fldd    d0 , [ AO1 ]
250         fldd    d1 , [ AO1, #8 ]
251
252         fldd    d4 , [ XO ]
253         fldd    d5 , [ XO, #8 ]
254
255         fmacd   d8  , d0,  d4
256         fmacd   d9  , d0,  d5
257
258         KMAC_R  d8  , d1,  d5
259         KMAC_I  d9  , d1,  d4
260
261         add     XO , XO, #16
262         add     AO1 , AO1, LDA
263
264
265 .endm
266
267 .macro SAVE_F1
268
269         fldd            d0, ALPHA_R
270         fldd            d1, ALPHA_I
271
272         fldmiad YO, { d4 - d5 }
273
274         FMAC_R1 d4 , d0 , d8
275         FMAC_I1 d5 , d0 , d9
276         FMAC_R2 d4 , d1 , d9
277         FMAC_I2 d5 , d1 , d8
278
279         fstmiad YO, { d4 - d5 }
280
281         add     YO, YO, #16
282
283 .endm
284
285 /****************************************************************************************/
286
287 .macro INIT_S4
288
289         fldd                    d8, FP_ZERO
290         vmov.f64                d9 , d8
291         vmov.f64                d10, d8
292         vmov.f64                d11, d8
293         vmov.f64                d12, d8
294         vmov.f64                d13, d8
295         vmov.f64                d14, d8
296         vmov.f64                d15, d8
297
298 .endm
299
300 .macro KERNEL_S4X4
301
302         KERNEL_S4X1
303         KERNEL_S4X1
304         KERNEL_S4X1
305         KERNEL_S4X1
306
307 .endm
308
309 .macro KERNEL_S4X1
310
311         fldd    d0 , [ AO1 ]
312         fldd    d1 , [ AO1, #8  ]
313         fldd    d2 , [ AO1, #16 ]
314         fldd    d3 , [ AO1, #24 ]
315
316         fldd    d4 , [ XO ]
317         fldd    d5 , [ XO, #8 ]
318
319         fmacd   d8  , d0,  d4
320         fmacd   d9  , d0,  d5
321         fmacd   d10 , d2,  d4
322         fmacd   d11 , d2,  d5
323
324         KMAC_R  d8  , d1,  d5
325         KMAC_I  d9  , d1,  d4
326         KMAC_R  d10 , d3,  d5
327         KMAC_I  d11 , d3,  d4
328
329         fldd    d0 , [ AO1, #32 ]
330         fldd    d1 , [ AO1, #40 ]
331         fldd    d2 , [ AO1, #48 ]
332         fldd    d3 , [ AO1, #56 ]
333
334         fmacd   d12 , d0,  d4
335         fmacd   d13 , d0,  d5
336         fmacd   d14 , d2,  d4
337         fmacd   d15 , d2,  d5
338
339         KMAC_R  d12 , d1,  d5
340         KMAC_I  d13 , d1,  d4
341         KMAC_R  d14 , d3,  d5
342         KMAC_I  d15 , d3,  d4
343
344         add     XO , XO, INC_X
345         add     AO1 , AO1, LDA
346         add     AO2 , AO2, LDA
347
348 .endm
349
350 .macro SAVE_S4
351
352         fldd            d0, ALPHA_R
353         fldd            d1, ALPHA_I
354
355         fldmiad YO, { d4 - d5 }
356
357         FMAC_R1 d4 , d0 , d8
358         FMAC_I1 d5 , d0 , d9
359         FMAC_R2 d4 , d1 , d9
360         FMAC_I2 d5 , d1 , d8
361
362         fstmiad YO, { d4 - d5 }
363
364         add     YO, YO, INC_Y
365
366         fldmiad YO, { d6 - d7 }
367
368         FMAC_R1 d6 , d0 , d10
369         FMAC_I1 d7 , d0 , d11
370         FMAC_R2 d6 , d1 , d11
371         FMAC_I2 d7 , d1 , d10
372
373         fstmiad YO, { d6 - d7 }
374
375         add     YO, YO, INC_Y
376
377         fldmiad YO, { d4 - d5 }
378
379         FMAC_R1 d4 , d0 , d12
380         FMAC_I1 d5 , d0 , d13
381         FMAC_R2 d4 , d1 , d13
382         FMAC_I2 d5 , d1 , d12
383
384         fstmiad YO, { d4 - d5 }
385
386         add     YO, YO, INC_Y
387
388         fldmiad YO, { d6 - d7 }
389
390         FMAC_R1 d6 , d0 , d14
391         FMAC_I1 d7 , d0 , d15
392         FMAC_R2 d6 , d1 , d15
393         FMAC_I2 d7 , d1 , d14
394
395         fstmiad YO, { d6 - d7 }
396
397         add     YO, YO, INC_Y
398
399 .endm
400
401
402
403
404 .macro INIT_S1
405
406         fldd                    d8, FP_ZERO
407         vmov.f64                d9 , d8
408
409 .endm
410
411 .macro KERNEL_S1X1
412
413         fldd    d0 , [ AO1 ]
414         fldd    d1 , [ AO1, #8 ]
415
416         fldd    d4 , [ XO ]
417         fldd    d5 , [ XO, #8 ]
418
419         fmacd   d8  , d0,  d4
420         fmacd   d9  , d0,  d5
421
422         KMAC_R  d8  , d1,  d5
423         KMAC_I  d9  , d1,  d4
424
425         add     XO , XO, INC_X
426         add     AO1 , AO1, LDA
427
428
429 .endm
430
431 .macro SAVE_S1
432
433         fldd            d0, ALPHA_R
434         fldd            d1, ALPHA_I
435
436         fldmiad YO, { d4 - d5 }
437
438         FMAC_R1 d4 , d0 , d8
439         FMAC_I1 d5 , d0 , d9
440         FMAC_R2 d4 , d1 , d9
441         FMAC_I2 d5 , d1 , d8
442
443         fstmiad YO, { d4 - d5 }
444
445         add     YO, YO, INC_Y
446
447 .endm
448
449
450
451 /**************************************************************************************
452 * End of macro definitions
453 **************************************************************************************/
454
455         PROLOGUE
456
457         .align 5
458         push    {r4 - r9 , fp}
459         add     fp, sp, #28
460         sub     sp, sp, #STACKSIZE                              // reserve stack
461
462         sub     r12, fp, #192
463
464 #if     defined(DOUBLE)
465         vstm    r12, { d8 - d15 }                                 // store floating point registers
466 #else
467         vstm    r12, { s8 - s15 }                                 // store floating point registers
468 #endif
469
470         movs    r12, #0
471         str     r12, FP_ZERO
472         str     r12, FP_ZERO_1
473
474         cmp     OLD_M, #0
475         ble     zgemvn_kernel_L999
476
477         cmp     N, #0
478         ble     zgemvn_kernel_L999
479
480 #if !defined(__ARM_PCS_VFP)
481         vldr    d0, OLD_ALPHAR
482         vldr    d1, OLD_ALPHAI
483         ldr     OLD_A, OLD_A_SOFTFP
484 #endif
485
486         str     OLD_A, A
487         str     OLD_M, M
488         vstr    d0 , ALPHA_R
489         vstr    d1 , ALPHA_I
490
491
492         ldr    INC_X , OLD_INC_X
493         ldr    INC_Y , OLD_INC_Y
494
495         cmp     INC_X, #0
496         beq     zgemvn_kernel_L999
497
498         cmp     INC_Y, #0
499         beq     zgemvn_kernel_L999
500
501         ldr     LDA, OLD_LDA
502
503
504 #if defined(DOUBLE)
505         lsl     LDA, LDA, #4                            // LDA * SIZE * 2
506 #else
507         lsl     LDA, LDA, #3                            // LDA * SIZE * 2
508 #endif
509
510         cmp     INC_X, #1
511         bne     zgemvn_kernel_S4_BEGIN
512
513         cmp     INC_Y, #1
514         bne     zgemvn_kernel_S4_BEGIN
515
516
517 zgemvn_kernel_F4_BEGIN:
518
519         ldr     YO , Y
520
521         ldr     I, M
522         asrs    I, I, #2                                        // I = M / 4
523         ble     zgemvn_kernel_F1_BEGIN
524
525 zgemvn_kernel_F4X4:
526
527         ldr     AO1, A
528         add     AO2, AO1, LDA
529         add     r3 , AO1, #64
530         str     r3 , A
531
532         add     AO2, AO2, LDA
533         add     AO2, AO2, LDA
534
535         ldr     XO , X
536
537         INIT_F4
538
539         asrs    J, N, #2                                        // J = N / 4
540         ble     zgemvn_kernel_F4X1
541
542
543 zgemvn_kernel_F4X4_10:
544
545         KERNEL_F4X4
546
547         subs    J, J, #1
548         bne     zgemvn_kernel_F4X4_10
549
550
551 zgemvn_kernel_F4X1:
552
553         ands    J, N , #3
554         ble     zgemvn_kernel_F4_END
555
556 zgemvn_kernel_F4X1_10:
557
558         KERNEL_F4X1
559
560         subs    J, J, #1
561         bne     zgemvn_kernel_F4X1_10
562
563
564 zgemvn_kernel_F4_END:
565
566         SAVE_F4
567
568         subs    I , I , #1
569         bne     zgemvn_kernel_F4X4
570
571
572 zgemvn_kernel_F1_BEGIN:
573
574         ldr     I, M
575         ands    I,  I , #3
576         ble     zgemvn_kernel_L999
577
578 zgemvn_kernel_F1X1:
579
580         ldr     AO1, A
581         add     r3, AO1, #16
582         str     r3, A
583
584         ldr     XO , X
585
586         INIT_F1
587
588         mov     J, N
589
590
591 zgemvn_kernel_F1X1_10:
592
593         KERNEL_F1X1
594
595         subs    J, J, #1
596         bne     zgemvn_kernel_F1X1_10
597
598
599 zgemvn_kernel_F1_END:
600
601         SAVE_F1
602
603         subs    I , I , #1
604         bne     zgemvn_kernel_F1X1
605
606         b       zgemvn_kernel_L999
607
608
609
610 /*************************************************************************************************************/
611
612 zgemvn_kernel_S4_BEGIN:
613
614 #if defined(DOUBLE)
615         lsl     INC_X, INC_X, #4                                // INC_X * SIZE * 2
616         lsl     INC_Y, INC_Y, #4                                // INC_Y * SIZE * 2
617 #else
618         lsl     INC_X, INC_X, #3                                // INC_X * SIZE * 2
619         lsl     INC_Y, INC_Y, #3                                // INC_Y * SIZE * 2
620 #endif
621
622         ldr     YO , Y
623
624         ldr     I, M
625         asrs    I, I, #2                                        // I = M / 4
626         ble     zgemvn_kernel_S1_BEGIN
627
628 zgemvn_kernel_S4X4:
629
630         ldr     AO1, A
631         add     AO2, AO1, LDA
632         add     r3 , AO1, #64
633         str     r3 , A
634
635         ldr     XO , X
636
637         INIT_S4
638
639         asrs    J, N, #2                                        // J = N / 4
640         ble     zgemvn_kernel_S4X1
641
642
643 zgemvn_kernel_S4X4_10:
644
645         KERNEL_S4X4
646
647         subs    J, J, #1
648         bne     zgemvn_kernel_S4X4_10
649
650
651 zgemvn_kernel_S4X1:
652
653         ands    J, N , #3
654         ble     zgemvn_kernel_S4_END
655
656 zgemvn_kernel_S4X1_10:
657
658         KERNEL_S4X1
659
660         subs    J, J, #1
661         bne     zgemvn_kernel_S4X1_10
662
663
664 zgemvn_kernel_S4_END:
665
666         SAVE_S4
667
668         subs    I , I , #1
669         bne     zgemvn_kernel_S4X4
670
671
672 zgemvn_kernel_S1_BEGIN:
673
674         ldr     I, M
675         ands    I,  I , #3
676         ble     zgemvn_kernel_L999
677
678 zgemvn_kernel_S1X1:
679
680         ldr     AO1, A
681         add     r3, AO1, #16
682         str     r3, A
683
684         ldr     XO , X
685
686         INIT_S1
687
688         mov     J, N
689
690
691 zgemvn_kernel_S1X1_10:
692
693         KERNEL_S1X1
694
695         subs    J, J, #1
696         bne     zgemvn_kernel_S1X1_10
697
698
699 zgemvn_kernel_S1_END:
700
701         SAVE_S1
702
703         subs    I , I , #1
704         bne     zgemvn_kernel_S1X1
705
706
707 /*************************************************************************************************************/
708
709 zgemvn_kernel_L999:
710
711         sub     r3, fp, #192
712
713 #if     defined(DOUBLE)
714         vldm    r3, { d8 - d15 }                                 // restore floating point registers
715 #else
716         vldm    r3, { s8 - s15 }                                 // restore floating point registers
717 #endif
718
719         mov     r0, #0          // set return value
720
721         sub     sp, fp, #28
722         pop     {r4 -r9 ,fp}
723         bx      lr
724
725         EPILOGUE
726