Merge pull request #733 from yuyichao/arm-asm
[platform/upstream/openblas.git] / kernel / arm / cgemv_t_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 #define OLD_LDA         [fp, #0 ]
42 #define X               [fp, #4 ]
43 #define OLD_INC_X       [fp, #8 ]
44 #define Y               [fp, #12 ]
45 #define OLD_INC_Y       [fp, #16 ]
46 #define OLD_A           r3
47 #define OLD_N           r1
48
49 #define M       r0
50 #define AO1     r1
51 #define J       r2
52
53 #define AO2     r4
54 #define XO      r5
55 #define YO      r6
56 #define LDA     r7
57 #define INC_X   r8
58 #define INC_Y   r9
59
60 #define I       r12
61
62 #define N       [fp, #-252 ]
63 #define A       [fp, #-256 ]
64
65
66 #define X_PRE   512
67 #define A_PRE   512
68
69 /**************************************************************************************
70 * Macro definitions
71 **************************************************************************************/
72
73 #if !defined(CONJ) && !defined(XCONJ)
74
75         #define KMAC_R  fnmacs
76         #define KMAC_I  fmacs
77
78         #define FMAC_R1 fmacs
79         #define FMAC_R2 fnmacs
80         #define FMAC_I1 fmacs
81         #define FMAC_I2 fmacs
82
83 #elif defined(CONJ) && !defined(XCONJ)
84
85         #define KMAC_R  fmacs
86         #define KMAC_I  fnmacs
87
88         #define FMAC_R1 fmacs
89         #define FMAC_R2 fnmacs
90         #define FMAC_I1 fmacs
91         #define FMAC_I2 fmacs
92
93 #elif !defined(CONJ) && defined(XCONJ)
94
95         #define KMAC_R  fmacs
96         #define KMAC_I  fnmacs
97
98         #define FMAC_R1 fmacs
99         #define FMAC_R2 fmacs
100         #define FMAC_I1 fnmacs
101         #define FMAC_I2 fmacs
102
103 #else
104
105         #define KMAC_R  fnmacs
106         #define KMAC_I  fmacs
107
108         #define FMAC_R1 fmacs
109         #define FMAC_R2 fmacs
110         #define FMAC_I1 fnmacs
111         #define FMAC_I2 fmacs
112
113 #endif
114
115
116
117 .macro INIT_F2
118
119         vldr.f32        s12, =0
120         vldr.f32        s13, =0
121         vldr.f32        s14, =0
122         vldr.f32        s15, =0
123
124 .endm
125
126 .macro KERNEL_F2X4
127
128         KERNEL_F2X1
129         KERNEL_F2X1
130         KERNEL_F2X1
131         KERNEL_F2X1
132
133 .endm
134
135 .macro KERNEL_F2X1
136
137         fldmias XO! ,  { s2 - s3 }
138         fldmias AO1!,  { s4 - s5 }
139         fldmias AO2!,  { s8 - s9   }
140
141         fmacs   s12 , s4 , s2
142         fmacs   s13 , s4 , s3
143         KMAC_R  s12 , s5 , s3
144         KMAC_I  s13 , s5 , s2
145
146         fmacs   s14 , s8 , s2
147         fmacs   s15 , s8 , s3
148         KMAC_R  s14 , s9 , s3
149         KMAC_I  s15 , s9 , s2
150
151 .endm
152
153 .macro  SAVE_F2
154
155         fldmias YO,  { s4 - s7 }
156
157         FMAC_R1 s4 , s0 , s12
158         FMAC_I1 s5 , s0 , s13
159         FMAC_R2 s4 , s1 , s13
160         FMAC_I2 s5 , s1 , s12
161
162         FMAC_R1 s6 , s0 , s14
163         FMAC_I1 s7 , s0 , s15
164         FMAC_R2 s6 , s1 , s15
165         FMAC_I2 s7 , s1 , s14
166
167         fstmias YO!, { s4 - s7 }
168
169 .endm
170
171 /************************************************************************************************/
172
173 .macro INIT_F1
174
175         vldr.f32        s12, =0
176         vldr.f32        s13, =0
177
178 .endm
179
180 .macro KERNEL_F1X4
181
182         KERNEL_F1X1
183         KERNEL_F1X1
184         KERNEL_F1X1
185         KERNEL_F1X1
186
187 .endm
188
189 .macro KERNEL_F1X1
190
191         fldmias XO! ,  { s2 - s3 }
192         fldmias AO1!,  { s4 - s5 }
193
194         fmacs   s12 , s4 , s2
195         fmacs   s13 , s4 , s3
196         KMAC_R  s12 , s5 , s3
197         KMAC_I  s13 , s5 , s2
198
199 .endm
200
201 .macro  SAVE_F1
202
203         fldmias YO,  { s4 - s5 }
204
205         FMAC_R1 s4 , s0 , s12
206         FMAC_I1 s5 , s0 , s13
207         FMAC_R2 s4 , s1 , s13
208         FMAC_I2 s5 , s1 , s12
209
210         fstmias YO!, { s4 - s5 }
211
212 .endm
213
214 /************************************************************************************************/
215
216 .macro INIT_S2
217
218         vldr.f32        s12, =0
219         vldr.f32        s13, =0
220         vldr.f32        s14, =0
221         vldr.f32        s15, =0
222
223 .endm
224
225 .macro KERNEL_S2X4
226
227         KERNEL_S2X1
228         KERNEL_S2X1
229         KERNEL_S2X1
230         KERNEL_S2X1
231
232 .endm
233
234 .macro KERNEL_S2X1
235
236         fldmias XO  ,  { s2 - s3 }
237         fldmias AO1!,  { s4 - s5 }
238         fldmias AO2!,  { s8 - s9   }
239
240         fmacs   s12 , s4 , s2
241         fmacs   s13 , s4 , s3
242         KMAC_R  s12 , s5 , s3
243         KMAC_I  s13 , s5 , s2
244
245         fmacs   s14 , s8 , s2
246         fmacs   s15 , s8 , s3
247         KMAC_R  s14 , s9 , s3
248         KMAC_I  s15 , s9 , s2
249
250         add     XO, XO, INC_X
251
252 .endm
253
254 .macro  SAVE_S2
255
256         fldmias YO,  { s4 - s5 }
257
258         FMAC_R1 s4 , s0 , s12
259         FMAC_I1 s5 , s0 , s13
260         FMAC_R2 s4 , s1 , s13
261         FMAC_I2 s5 , s1 , s12
262
263         fstmias YO,  { s4 - s5 }
264
265         add     YO, YO, INC_Y
266
267         fldmias YO,  { s6 - s7 }
268
269         FMAC_R1 s6 , s0 , s14
270         FMAC_I1 s7 , s0 , s15
271         FMAC_R2 s6 , s1 , s15
272         FMAC_I2 s7 , s1 , s14
273
274         fstmias YO,  { s6 - s7 }
275
276         add     YO, YO, INC_Y
277
278 .endm
279
280 /************************************************************************************************/
281
282 .macro INIT_S1
283
284         vldr.f32        s12, =0
285         vldr.f32        s13, =0
286
287 .endm
288
289 .macro KERNEL_S1X4
290
291         KERNEL_S1X1
292         KERNEL_S1X1
293         KERNEL_S1X1
294         KERNEL_S1X1
295
296 .endm
297
298 .macro KERNEL_S1X1
299
300         fldmias XO  ,  { s2 - s3 }
301         fldmias AO1!,  { s4 - s5 }
302
303         fmacs   s12 , s4 , s2
304         fmacs   s13 , s4 , s3
305         KMAC_R  s12 , s5 , s3
306         KMAC_I  s13 , s5 , s2
307
308         add     XO, XO, INC_X
309
310 .endm
311
312 .macro  SAVE_S1
313
314         fldmias YO,  { s4 - s5 }
315
316         FMAC_R1 s4 , s0 , s12
317         FMAC_I1 s5 , s0 , s13
318         FMAC_R2 s4 , s1 , s13
319         FMAC_I2 s5 , s1 , s12
320
321         fstmias YO,  { s4 - s5 }
322
323         add     YO, YO, INC_Y
324
325 .endm
326
327
328
329 /**************************************************************************************
330 * End of macro definitions
331 **************************************************************************************/
332
333         PROLOGUE
334
335         .align 5
336         push    {r4 - r9 , fp}
337         add     fp, sp, #28
338         sub     sp, sp, #STACKSIZE                              // reserve stack
339
340         sub     r12, fp, #192
341
342 #if     defined(DOUBLE)
343         vstm    r12, { d8 - d15 }                                 // store floating point registers
344 #else
345         vstm    r12, { s8 - s15 }                                 // store floating point registers
346 #endif
347
348         cmp     M, #0
349         ble     cgemvt_kernel_L999
350
351         cmp     OLD_N, #0
352         ble     cgemvt_kernel_L999
353
354         str     OLD_A, A
355         str     OLD_N, N
356
357         ldr    INC_X , OLD_INC_X
358         ldr    INC_Y , OLD_INC_Y
359
360         cmp     INC_X, #0
361         beq     cgemvt_kernel_L999
362
363         cmp     INC_Y, #0
364         beq     cgemvt_kernel_L999
365
366         ldr     LDA, OLD_LDA
367
368
369 #if defined(DOUBLE)
370         lsl     LDA, LDA, #4                            // LDA * SIZE
371 #else
372         lsl     LDA, LDA, #3                            // LDA * SIZE
373 #endif
374
375         cmp     INC_X, #1
376         bne     cgemvt_kernel_S2_BEGIN
377
378         cmp     INC_Y, #1
379         bne     cgemvt_kernel_S2_BEGIN
380
381
382 cgemvt_kernel_F2_BEGIN:
383
384         ldr     YO , Y
385
386         ldr     J, N
387         asrs    J, J, #1                                        // J = N / 2
388         ble     cgemvt_kernel_F1_BEGIN
389
390 cgemvt_kernel_F2X4:
391
392         ldr     AO1, A
393         add     AO2, AO1, LDA
394         add     r3 , AO2, LDA
395         str     r3 , A
396
397         ldr     XO , X
398
399         INIT_F2
400
401         asrs    I, M, #2                                        // I = M / 4
402         ble     cgemvt_kernel_F2X1
403
404
405 cgemvt_kernel_F2X4_10:
406
407         KERNEL_F2X4
408
409         subs    I, I, #1
410         bne     cgemvt_kernel_F2X4_10
411
412
413 cgemvt_kernel_F2X1:
414
415         ands    I, M , #3
416         ble     cgemvt_kernel_F2_END
417
418 cgemvt_kernel_F2X1_10:
419
420         KERNEL_F2X1
421
422         subs    I, I, #1
423         bne     cgemvt_kernel_F2X1_10
424
425
426 cgemvt_kernel_F2_END:
427
428         SAVE_F2
429
430         subs    J , J , #1
431         bne     cgemvt_kernel_F2X4
432
433
434 cgemvt_kernel_F1_BEGIN:
435
436         ldr     J, N
437         ands    J, J, #1
438         ble     cgemvt_kernel_L999
439
440 cgemvt_kernel_F1X4:
441
442         ldr     AO1, A
443
444         ldr     XO , X
445
446         INIT_F1
447
448         asrs    I, M, #2                                        // I = M / 4
449         ble     cgemvt_kernel_F1X1
450
451
452 cgemvt_kernel_F1X4_10:
453
454         KERNEL_F1X4
455
456         subs    I, I, #1
457         bne     cgemvt_kernel_F1X4_10
458
459
460 cgemvt_kernel_F1X1:
461
462         ands    I, M , #3
463         ble     cgemvt_kernel_F1_END
464
465 cgemvt_kernel_F1X1_10:
466
467         KERNEL_F1X1
468
469         subs    I, I, #1
470         bne     cgemvt_kernel_F1X1_10
471
472
473 cgemvt_kernel_F1_END:
474
475         SAVE_F1
476
477         b       cgemvt_kernel_L999
478
479
480
481 /*************************************************************************************************************/
482
483 cgemvt_kernel_S2_BEGIN:
484
485 #if defined(DOUBLE)
486         lsl     INC_X, INC_X, #4                                // INC_X * SIZE
487         lsl     INC_Y, INC_Y, #4                                // INC_Y * SIZE
488 #else
489         lsl     INC_X, INC_X, #3                                // INC_X * SIZE
490         lsl     INC_Y, INC_Y, #3                                // INC_Y * SIZE
491 #endif
492
493         ldr     YO , Y
494
495         ldr     J, N
496         asrs    J, J, #1                                        // J = N / 2
497         ble     cgemvt_kernel_S1_BEGIN
498
499 cgemvt_kernel_S2X4:
500
501         ldr     AO1, A
502         add     AO2, AO1, LDA
503         add     r3 , AO2, LDA
504         str     r3 , A
505
506         ldr     XO , X
507
508         INIT_S2
509
510         asrs    I, M, #2                                        // I = M / 4
511         ble     cgemvt_kernel_S2X1
512
513
514 cgemvt_kernel_S2X4_10:
515
516         KERNEL_S2X4
517
518         subs    I, I, #1
519         bne     cgemvt_kernel_S2X4_10
520
521
522 cgemvt_kernel_S2X1:
523
524         ands    I, M , #3
525         ble     cgemvt_kernel_S2_END
526
527 cgemvt_kernel_S2X1_10:
528
529         KERNEL_S2X1
530
531         subs    I, I, #1
532         bne     cgemvt_kernel_S2X1_10
533
534
535 cgemvt_kernel_S2_END:
536
537         SAVE_S2
538
539         subs    J , J , #1
540         bne     cgemvt_kernel_S2X4
541
542
543 cgemvt_kernel_S1_BEGIN:
544
545         ldr     J, N
546         ands    J, J, #1
547         ble     cgemvt_kernel_L999
548
549 cgemvt_kernel_S1X4:
550
551         ldr     AO1, A
552
553         ldr     XO , X
554
555         INIT_S1
556
557         asrs    I, M, #2                                        // I = M / 4
558         ble     cgemvt_kernel_S1X1
559
560
561 cgemvt_kernel_S1X4_10:
562
563         KERNEL_S1X4
564
565         subs    I, I, #1
566         bne     cgemvt_kernel_S1X4_10
567
568
569 cgemvt_kernel_S1X1:
570
571         ands    I, M , #3
572         ble     cgemvt_kernel_S1_END
573
574 cgemvt_kernel_S1X1_10:
575
576         KERNEL_S1X1
577
578         subs    I, I, #1
579         bne     cgemvt_kernel_S1X1_10
580
581
582 cgemvt_kernel_S1_END:
583
584         SAVE_S1
585
586
587
588 /*************************************************************************************************************/
589
590 cgemvt_kernel_L999:
591
592         sub     r3, fp, #192
593
594 #if     defined(DOUBLE)
595         vldm    r3, { d8 - d15 }                                 // restore floating point registers
596 #else
597         vldm    r3, { s8 - s15 }                                 // restore floating point registers
598 #endif
599
600         mov     r0, #0          // set return value
601
602         sub     sp, fp, #28
603         pop     {r4 -r9 ,fp}
604         bx      lr
605
606         EPILOGUE
607