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